顺序提取单个位的想法还不错。如果做得好,它可能几乎与任何其他解决方案一样快。
粒度为g的流中任意位置的位序列,例如对于(16 位)word
s 的流,g=16,可以在大小为 g 的块上逐块处理。
s
要从流中提取通过e
(with )位置的位(e - s) <= g
作为“右对齐”数字,示例实现可能是:
shift = s % g
lowerBits = data[ floor( s / g ) ] >> shift
upperBits = data[ floor( e / g ) ] << (g - shift)
bitSequence = (lowerBits | upperBits) & ( (1 << (e-s)) -1 )[*]
[*] 这最后一项只是掩盖了我们可能得到的任何不需要的高位,并将它们0
放在最终结果中。
(注意数据的字节顺序:))
这是否真的会加快速度通常无法确定。(取决于正在处理的数据、底层计算硬件、使用的编译器等。请注意,需要一些除法和一次模运算,这可能会显着减慢算法速度。)
可以以相同的方式非常有效地逐个提取位。例如:
blockIndex = floor( bitPosition / g )
bitIndex = bitPosition % g
nextBit = (data[ blockIndex ] >> bitIndex) & 1
这当然可以优化以避免重新计算blockIndex
以及bitIndex
如果和何时bitPosition
总是只增加 1。
另一种常见的方法是使用变量“掩码”来提取单个位:
mask = 1
index = 0
while ( not all bits read ) {
block = data[index]
if ( mask & block != 0 ) {
// a 1 was encountered
} else {
// a 0 was encountered
}
mask = mask << 1
if ( mask == 0 ) {
mask = 1
index = index + 1
}
}
请注意如何mask
使用它来屏蔽当前位并跟踪何时前进到下一个数据块。为此mask
,当然必须与g
数据块具有相同的宽度。
总结一下:
我认为,在一般情况下,该解决方案不会比每次读取一次循环迭代更有效,并且任何优化只会稍微改变一个方向或另一个方向的性能。