【问题标题】:Calculating Hamming Weight in O(1) [duplicate]在 O(1) 中计算汉明权重
【发布时间】:2013-03-05 20:08:00
【问题描述】:

在二进制表示中,汉明权重是 1 的个数。我在网上找到了一个 O(1) 的答案:

v = v - ((v>>1) & 0x55555555);
v = (v & 0x33333333) + ((v>>2) & 0x33333333);
int count = ((v + (v>>4) & 0xF0F0F0F) * 0x1010101) >> 24;

但是我不太了解该算法,也无法在任何地方找到它的描述。谁能解释一下,尤其是最后一行(*0x1010101 然后 >> 24 到底是什么意思)?

【问题讨论】:

  • 旁注:它实际上不是O(1)。比特数是O(log(n)),而简单的循环是O(n)。对于固定的整数大小,这个循环和直接循环都是O(1)
  • @Mysticial 是的,如果我们考虑 32 位整数,它们都是 O(1)。但是这个应该比迭代计数快吧?
  • @NSF - 是的,它可能比迭代计数更快(尽管它确实有乘法,所以......),但这不是 Big-Oh 分析的目的。 Big-Oh 指的是运行时间作为输入大小的函数增长的速度。在 Big-Oh 中,线性计数为 O(n),而此算法为 O(log(n)),渐近性确实更好,但有时可能需要特定的 n 值才能使渐近性更快的算法性能更好.
  • 我不确定这是否算作O(log(n))。它是O(log(n)) timewise,是的,但它通过要求 O(n) 并行化来实现这一点,以某种方式加起来 O(n) 总计算能力(如果你在整个 [大] 文件)。

标签: algorithm bit-manipulation


【解决方案1】:

这是用于计数位的分而治之策略的一部分,称为“人口”函数。 Reingold 和 Nievergelt,1977 年对这种策略的学术处理可以找到。

这个想法是首先对位求和,然后是 4 位,然后是 8 位,依此类推。例如,如果您有位 1011,则第一对 10 变为 01,因为有一个位,第二对变为 10,因为二进制中的 10 = 211 中有两个位.这里的基本事实是:

population(x) = x - (x/2) - (x/4) - (x/8) - (x/16) - ... etc.

您拥有的确切算法是所谓的“HAKMEM”算法的变体(参见 Beeler、Gosper 和 Schroppel,1972 年)。该算法并行计算 4 位字段中的1,然后将这些和转换为 8 位和。最后一步是通过乘以 0x01010101 来添加这 4 个字节的操作。 0x0F0F0F0F 掩码通过屏蔽非总和信息来获取 4 位字节总和。例如,假设 8 位字段是 10110110,那么有 5 位等于 0101,因此我们将有 10110101。只有最后四位是有效的,所以我们屏蔽了前四位,即:

10110101 & 0x0F = 00000101

您可以在亨利·沃伦 (Henry Warren) 的《黑客的喜悦》(Hacker's Delight) 一书中找到关于计数细节的整章。

【讨论】:

    猜你喜欢
    • 2010-11-04
    • 1970-01-01
    • 1970-01-01
    • 2016-07-02
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    • 2016-09-09
    • 1970-01-01
    相关资源
    最近更新 更多