【问题标题】:How can I check Hamming Weight without converting to binary?如何在不转换为二进制的情况下检查汉明权重?
【发布时间】:2009-05-09 18:54:53
【问题描述】:

如何在不实际转换和计数的情况下以二进制表示形式获得 “1”的数量

例如

  def number_of_ones(n):
      # do something
      # I want to MAKE this FASTER (computationally less complex).
      c = 0
      while n:
        c += n%2
        n /= 2
      return c


>>> number_of_ones(5)
    2
>>> number_of_ones(4)
    1

【问题讨论】:

标签: python algorithm discrete-mathematics


【解决方案1】:

我不是 python 程序员,但希望它足以让你跟随。

c = 0
while n:
    c += 1
    n &= n - 1

return c

虽然有点晦涩,但它的主要优势是速度和简单性。对于 n 中设置为 1 的每个位,while 循环仅迭代一次。

【讨论】:

    【解决方案2】:

    您无法降低计算的复杂性。它将是 O(n) 的位数,或者,正如 & 技巧的答案所示,O(n) 设置为 1 的位数;但除非您使用的所有数字都是特殊情况,否则后者平均应为 n/2,因此这两个 O(n) 数字是相同的。

    当然,查找表技巧实际上对计算复杂性没有任何作用;它只是用空间为时间付出代价,但不会改变基本的经济学原理,即您必须以某种方式检查每一位,并且没有办法解决这个问题。从逻辑上讲,如果不检查每个位,就无法回答有关数字中的位的问题。

    现在,我想我有点草率,因为其中许多示例实际上都是 O(n^2),因为在 Python 中,您必须一次检查整数,所以使用 Python 长整数,比如说, 100 个字节,一个 + 或一个 & 或一个 / 操作将至少查看每个字节一次,并且会一遍又一遍地发生,直到数字减少到零(在上面概述的方案中),所以这些再次是真正的 O(n^2) 操作。我不确定 Python 是否会在这里允许真正的 O(n) 解决方案。

    无论如何:如果您真的在询问 计算 复杂性,这具体意味着大 O 分析,这就是您的答案。 :-)

    【讨论】:

      【解决方案3】:

      IMO,一个好方法是使用查找表 - 创建一个字典,将字节转换为 1 的数量(您可以使用您发布的代码来生成它,它只需要运行一次),并且然后使用这样的东西:

      def number_of_ones(n):
          sum = 0
          while n != 0:
              sum += lookup_table[n & 0xff]
              n >>= 8
          return sum
      

      我相信这是空间和运行时间之间相当不错的折衷。

      【讨论】:

        【解决方案4】:

        如果你想在一行中完成,你可以使用:

        sum( [x&(1<<i)>0 for i in range(32)] )
        

        【讨论】:

          【解决方案5】:

          https://en.wikipedia.org/wiki/Hamming_weight.

          O(log(n)) 的解,n 是位长

          m1  = 0x5555555555555555 #binary: 0101...
          m2  = 0x3333333333333333 #binary: 00110011..
          m4  = 0x0f0f0f0f0f0f0f0f #binary:  4 zeros,  4 ones ...
          m8  = 0x00ff00ff00ff00ff #binary:  8 zeros,  8 ones ...
          m16 = 0x0000ffff0000ffff #binary: 16 zeros, 16 ones ...
          m32 = 0x00000000ffffffff #binary: 32 zeros, 32 ones
          h01 = 0x0101010101010101 #the sum of 256 to the power of 0,1,2,3...
          
          def hammingWeight(x: int) -> int:
              x -= (x>>1)&m1
              x = (x&m2) + ((x>>2)&m2)
              x = (x+(x>>4))&m4
              return ((x*h01)>>56)&0x7f
          

          而在python 3.10中,int类型会有一个bit_count()方法

          【讨论】:

            【解决方案6】:

            如果您真的关心速度,可以用 C 编写代码(参见 this question 了解如何),并使用类似 ctypes 的方式与 C 实现接口。

            【讨论】:

            • 我关心的是计算复杂度,而不是实际速度或语言。
            【解决方案7】:

            这里:

            def bitCount(int_no):
            
                c = 0
                while(int_no):
                    int_no &= (int_no - 1)
                    c += 1
                return c
            

            这可能是一种古老而有效的方法......最初是用 C 实现的(Algo 有一个我不记得的名字)。对我来说很好,希望对其他人也有用

            【讨论】:

              【解决方案8】:

              p= lambda n:n 和 1+p(n&(n-1))

              这使用了短路和递归,当n大于0时,它切换到计算1+p(n&(n-1)),其中调用p(n&(n-1))等等,当n 为 0,它返回 0。复杂度为 O(n),因为它运行二进制文件中存在的数量的次数。

              示例:p(9)=1+p(8)=1+1+p(0)=1+1+0=2

              【讨论】:

              • 如果这是一个有效的答案,加上一些解释会更有价值。
              猜你喜欢
              • 1970-01-01
              • 2010-12-05
              • 2021-12-27
              • 1970-01-01
              • 2019-07-10
              • 2014-05-26
              • 1970-01-01
              • 2019-03-22
              相关资源
              最近更新 更多