顺序提取单个位的想法还不错。如果做得好,它可能几乎和任何其他解决方案一样快。
粒度流中任意位置的位序列g,例如对于(16 位)words 的流,g=16,可以在块上逐块处理大小为 g。
要从流中提取位置s 到e(带有(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。
总结一下:
我认为,在一般情况下,该解决方案不会比每次读取一次循环迭代更有效,任何优化只会稍微改变一个方向或另一个方向的性能。