如何计算数字中的集合位位置?
How to calculate the set bit positions in a number?
如果二进制 n = 100011,那么我想检索设置位的位置,在这种情况下,从左到右测量时为 1、5、6。
如何在不通过逐位检查位是否为零的情况下计算此类位置?
要做到这一点,你需要使用面具。
从右到左的每个位置都是 2 的幂。
例如 0101
是 1*2ˆ0 + 0*2ˆ1 + 1*2ˆ2 + 0*1ˆ3 = 1+0+4+0 = 5
然后检查这两个位是否针对 bytesToTest
变量打开 AND
with 5: 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
有了这些信息,您应该能够为每个位定义单独的掩码,一个一个地测试,并能够回答您在哪个位置找到打开的位以及在哪个位置找到关闭的位。
在最常见的约定中,二进制数的书写顺序与其他常见位置表示法(十进制等)中的数字相同:最低有效位在最右边的位置。将该数字标记为 "digit zero" 也更有意义,这样每个数字的标签都对应于相关权重中的指数(例如,位 0 的权重为 20= 1 等等)。这并不重要,重新编号数字很容易,但通常更容易遵循约定。
既然你问了
How to calculate such positions without literally checking for bit is zero or not by going to every bit position?
我将解决问题的那一部分。然而,逐位检查并不是完全灾难性的。即使对于 BigInts。无论如何,结果的数量可能与位数一样多。对于已知 稀疏 的数字,仍然没有太多可以做的 - 必须检查每一位 somehow 因为如果忽略任何一位完全,那位可能已经设置,我们会错过它。但是在机器字的上下文中,有技巧,例如基于find-first-set。
使用find-first-set函数(或计算尾随零),可以在一步中找到具有最低索引的设置位的索引(如果您接受此函数为一步,则为大多数硬件上的合理假设,理论上您可以将其定义为一个步骤),然后可以删除该位,以便下一个 find-first-set 将找到 next[=28 的索引=] 位。例如:
while bitmask != 0:
yield return find-first-set(bitmask)
bitmask &= bitmask - 1 // remove lowest set bit
这很容易适应 BigInts,只需在数字的每个分支上执行此操作并添加适当的偏移量即可。
如果二进制 n = 100011,那么我想检索设置位的位置,在这种情况下,从左到右测量时为 1、5、6。
如何在不通过逐位检查位是否为零的情况下计算此类位置?
要做到这一点,你需要使用面具。
从右到左的每个位置都是 2 的幂。
例如 0101
是 1*2ˆ0 + 0*2ˆ1 + 1*2ˆ2 + 0*1ˆ3 = 1+0+4+0 = 5
然后检查这两个位是否针对 bytesToTest
变量打开 AND
with 5: 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
有了这些信息,您应该能够为每个位定义单独的掩码,一个一个地测试,并能够回答您在哪个位置找到打开的位以及在哪个位置找到关闭的位。
在最常见的约定中,二进制数的书写顺序与其他常见位置表示法(十进制等)中的数字相同:最低有效位在最右边的位置。将该数字标记为 "digit zero" 也更有意义,这样每个数字的标签都对应于相关权重中的指数(例如,位 0 的权重为 20= 1 等等)。这并不重要,重新编号数字很容易,但通常更容易遵循约定。
既然你问了
How to calculate such positions without literally checking for bit is zero or not by going to every bit position?
我将解决问题的那一部分。然而,逐位检查并不是完全灾难性的。即使对于 BigInts。无论如何,结果的数量可能与位数一样多。对于已知 稀疏 的数字,仍然没有太多可以做的 - 必须检查每一位 somehow 因为如果忽略任何一位完全,那位可能已经设置,我们会错过它。但是在机器字的上下文中,有技巧,例如基于find-first-set。
使用find-first-set函数(或计算尾随零),可以在一步中找到具有最低索引的设置位的索引(如果您接受此函数为一步,则为大多数硬件上的合理假设,理论上您可以将其定义为一个步骤),然后可以删除该位,以便下一个 find-first-set 将找到 next[=28 的索引=] 位。例如:
while bitmask != 0:
yield return find-first-set(bitmask)
bitmask &= bitmask - 1 // remove lowest set bit
这很容易适应 BigInts,只需在数字的每个分支上执行此操作并添加适当的偏移量即可。