如果n = 100011是二进制的,那么我想检索设置位的位置,在这种情况下从左到右测量时为1.5,6。
如何通过转到每个位位置来计算这些位置而不是逐字检查位是否为零?
答案 0 :(得分:1)
要做到这一点,你要使用面具。
从右到左的每个位置都是2的幂。
例如,0101
为1*2ˆ0 + 0*2ˆ1 + 1*2ˆ2 + 0*1ˆ3 = 1+0+4+0 = 5
然后检查这两个位是否与bytesToTest
变量对AND
变量一起开启byteToTest & 5 == 5
鉴于1 & 0 = 0
和1 & 1 = 1
如果bytesToTest是1111那么1111& 0101将给0101
如果bytesToTest是1010那么1010& 0101将给出0000
根据100011的特定情况的推理 从左到右检索1,5和6(三个设置为1)
面具是:1+2+32 = 35
使用此信息,您应该能够为每个位定义单独的掩码,逐个测试,并且能够回答您在哪个位置找到已打开的位以及哪些位已关闭。
答案 1 :(得分:1)
在最常见的约定中,二进制数按顺序写入其他常见位置表示(十进制等)中的数字:最右边位置的最低有效数字。将该数字标记为“数字零”更有意义,因此每个数字的标签对应于相关权重中的指数(例如,位0具有权重2 0 = 1等等)。这并不重要,重新编号数字很容易,但通常更容易遵循惯例。
你问过
如何通过转到每个位位置来计算这些位置而不是逐字检查位是否为零?
我将解决问题的这一部分。然而,逐个检查位并不是完全灾难性的。即使是BigInts。无论如何,结果的数量可能与位数一样高。对于已知稀疏的数字,仍然没有太多可以做的事情 - 每个位都必须以某种方式检查 因为如果任何位被完全忽略,那么该位可能有已经设定,我们会想念它。但是在机器词的上下文中,有一些技巧,例如基于find-first-set。
使用find-first-set函数(或计数尾随零),可以在一个步骤中找到具有最低索引的设置位的索引(如果您将此函数视为一步,这是一个合理的假设在大多数硬件上,理论上你可以将它定义为一步),然后可以删除该位,以便下一个查找第一组将找到 next 位的索引。例如:
while bitmask != 0:
yield return find-first-set(bitmask)
bitmask &= bitmask - 1 // remove lowest set bit
这很容易适应BigInts,只需在数字的每个肢体上执行此操作并添加适当的偏移量。