【问题标题】:Python: Set Bits Count (popcount)Python:设置位计数(popcount)
【发布时间】:2010-09-29 06:51:42
【问题描述】:

在我的数据库(oracle 11g)中复制了几个 blob,使用 UTL_RAW.BIT_XOR 对 blob 执行了 XOR 操作。之后我想计算二进制字符串中设置的位数,所以写了上面的代码。

在一个小实验中,我想看看生成的十六进制和整数值是什么,并编写了这个程序..

SQL> declare
2
3 vblob1 blob;
4
5 BEGIN
6
7 select leftiriscode INTO vblob1 FROM irisdata WHERE irisid=1;
8
9 dbms_output.put_line(rawtohex(vblob1));
10
11
12 dbms_output.put_line(UTL_RAW.CAST_TO_binary_integer(vblob1));
13
14
15 END;
16 /

输出:十六进制:

0F0008020003030D030C1D1C3C383C330A3311373724764C54496C0A6B029B84840547A341BBA83D
BB5FB9DE4CDE5EFE96E1FC6169438344D604681D409F9F9F3BC07EE0C4E0C033A23B37791F59F84F
F94E4F664E3072B0229DA09D9F0F1FC600C2E380D6988C198B39517D157E7D66FE675237673D3D28
3A016C01411003343C76740F710F0F4F8FE976E1E882C186D316A63C0C7D7D7D7D397F016101B043
0176C37E767C7E0C7D010C8302C2D3E4F2ACE42F8D3F3F367A46F54285434ABB61BDB53CBF6C7CC0
F4C1C3F349B3F7BEB30E4A0CFE1C85180DC338C2C1C6E7A5CE3104303178724CCC5F451F573F3B24
7F24052000202003291F130F1B0E070C0E0D0F0E0F0B0B07070F1E1B330F27073F3F272E2F2F6F7B
2F2E1F2E4F7EFF7EDF3EBF253F3D2F39BF3D7F7FFED72FF39FE7773DBE9DBFBB3FE7A76E777DF55C
5F5F7ADF7FBD7F6AFE7B7D1FBE7F7F7DD7F63FBFBF2D3B7F7F5F2F7F3D7F7D3B3F3B7FFF4D676F7F
5D9FAD7DD17F7F6F6F0B6F7F3F767F1779364737370F7D3F5F377F2F3D3F7F1F2FE7709FB7BCB77B
0B77CF1DF5BF1F7F3D3E4E7F197F571F7D7E3F7F7F7D7F6F4F75FF6F7ECE2FFF793EFFEDB7BDDD1F
FF3BCE3F7F3FBF3D6C7FFF7F7F4FAF7F6FFFFF8D7777BF3AE30FAEEEEBCF5FEEFEE75FFEACFFDF0F
DFFFF77FFF677F4FFF7F7F1B5F1F5F146F1F1E1B3B1F3F273303170F370E250B

INTEGER VALUE: 15

十六进制代码和产生的整数值之间存在差异,因此使用以下python代码检查实际整数值。

print int("0F0008020003030D030C1D1C3C383C330A3311373724764C54496C0A6B029B84840547A341BBA83D
BB5FB9DE4CDE5EFE96E1FC6169438344D604681D409F9F9F3BC07EE0C4E0C033A23B37791F59F84F
F94E4F664E3072B0229DA09D9F0F1FC600C2E380D6988C198B39517D157E7D66FE675237673D3D28
3A016C01411003343C76740F710F0F4F8FE976E1E882C186D316A63C0C7D7D7D7D397F016101B043
0176C37E767C7E0C7D010C8302C2D3E4F2ACE42F8D3F3F367A46F54285434ABB61BDB53CBF6C7CC0
F4C1C3F349B3F7BEB30E4A0CFE1C85180DC338C2C1C6E7A5CE3104303178724CCC5F451F573F3B24
7F24052000202003291F130F1B0E070C0E0D0F0E0F0B0B07070F1E1B330F27073F3F272E2F2F6F7B
2F2E1F2E4F7EFF7EDF3EBF253F3D2F39BF3D7F7FFED72FF39FE7773DBE9DBFBB3FE7A76E777DF55C
5F5F7ADF7FBD7F6AFE7B7D1FBE7F7F7DD7F63FBFBF2D3B7F7F5F2F7F3D7F7D3B3F3B7FFF4D676F7F
5D9FAD7DD17F7F6F6F0B6F7F3F767F1779364737370F7D3F5F377F2F3D3F7F1F2FE7709FB7BCB77B
0B77CF1DF5BF1F7F3D3E4E7F197F571F7D7E3F7F7F7D7F6F4F75FF6F7ECE2FFF793EFFEDB7BDDD1F
FF3BCE3F7F3FBF3D6C7FFF7F7F4FAF7F6FFFFF8D7777BF3AE30FAEEEEBCF5FEEFEE75FFEACFFDF0F
DFFFF77FFF677F4FFF7F7F1B5F1F5F146F1F1E1B3B1F3F273303170F370E250B",16)

答案:

611951595100708231079693644541095422704525056339295086455197024065285448917042457
942011979060274412229909425184116963447100932992139876977824261789243946528467423
887840013630358158845039770703659333212332565531927875442166643379024991542726916
563271158141698128396823655639931773363878078933197184072343959630467756337300811
165816534945075483141582643531294791665590339000206551162697220540050652439977992
246472159627917169957822698172925680112854091876671868161705785698942483896808137
210721991100755736178634253569843464062494863175653771387230991126430841565373390
924951878267929443498220727531299945275045612499928105876210478958806304156695438
684335624641395635997624911334453040399012259638042898470872203581555352191122920
004010193837249388365999010692555403377045768493630826307316376698443166439386014
145858084176544890282148970436631175577000673079418699845203671050174181808397880
048734270748095682582556024378558289251964544327507321930196203199459115159756564
507340111030285226951393012863778670390172056906403480159339130447254293412506482
027099835944315172972281427649277354815211185293109925602315480350955479477144523
387689192243720928249121486221114300503766209279369960344185651810101969585926336
07333771272398091

为了获得设置位计数,我用 C 语言编写了以下代码:

int bitsoncount(unsigned x)
{
    unsigned int b=0;
    if(x > 1)
        b=1;    
    while(x &= (x - 1))
        b++;    
    return b;
}

当我在 python 中尝试相同的代码时,它不起作用。由于我正在试验的好奇心,我是 python 的新手,如果错了,请原谅。

def bitsoncount(x):
b=0;
if(x>1):
b=1;
while(x &= (x-1)):

我在最后一行遇到错误,需要一些帮助来解决这个问题并在 python 中实现逻辑:-)

在我看到之后,我有兴趣在 python 中查看 set bits 版本!

相关问题:Best algorithm to count the number of set bits in a 32-bit integer?

【问题讨论】:

标签: python bit-manipulation


【解决方案1】:

Python 2.6 或 3.0:

def bitsoncount(x):
    return bin(x).count('1')

例子:

>>> x = 123
>>> bin(x)
'0b1111011'
>>> bitsoncount(x) 
6

或者

Matt Howells's answer 在 Python 中:

def bitsoncount(i):
    assert 0 <= i < 0x100000000
    i = i - ((i >> 1) & 0x55555555)
    i = (i & 0x33333333) + ((i >> 2) & 0x33333333)
    return (((i + (i >> 4) & 0xF0F0F0F) * 0x1010101) & 0xffffffff) >> 24

【讨论】:

  • 虽然这很好,但我希望你能找到一种方法来避免在初学者的答案中使用 lambda。函数 def 对初学者来说更清晰。第二行代码帮助他们看到主体和意图。它为他们提供了放置文档字符串的地方。
  • 顺便说一句,@gnud 的版本比 bin(x).count('1') 慢 4 倍。
  • 我的基本基准测试显示bin(x).count('1') 比 Matt Howell 的函数快 23%。这也更容易理解。
  • @FoxyLad:正如我在上面的评论中所说,基于bin() 的变体在我的机器上快了 1.5 倍。此外,bin() 支持 问题要求 的长整数,这与马特的回答不同,请参阅代码中的断言语句。马特的答案是为从 google 发送的对bit-twiddling hacks 感兴趣的人提供的。
【解决方案2】:

您要查找的内容称为Hamming Weight

在 python 2.6/3.0 中可以很容易地找到它:

bits = sum( b == '1' for b in bin(x)[2:] )

【讨论】:

    【解决方案3】:

    从 Python 3.10 开始,您可以使用 int.bit_count():

    x = 826151739
    
    print(x.bit_count()) # 16
    

    【讨论】:

      【解决方案4】:

      您使用的是哪个版本的 Python? 首先,Python 使用空格而不是分号,所以开始它应该看起来像这样......

        def bitsoncount(x): 
            b=0
            while(x > 0):
                x &= x - 1   
                b+=1
            return b
      

      【讨论】:

      • 此代码错误。 bitsoncount(2) 必须是 1。您的代码返回2
      • 谢谢塞巴斯蒂安。我不明白算法做了什么,我只是想展示 Python 中空格的正确使用,但现在已经修复了。
      【解决方案5】:

      你的C算法直接翻译如下:

      def bitsoncount(x):
          b = 0
          while x > 0:
              x &= x - 1
              b += 1
          return b
      

      【讨论】:

      • 嗯——现在不再是直接翻译他的代码了——我没有选择简单的 =)
      【解决方案6】:

      也许这就是你的意思?

      def bits_on_count(x):
          b = 0
          while x != 0:
              if x & 1: # Last bit is a 1
                  b += 1
              x >>= 1 # Shift the bits of x right
          return b
      

      还有一种方法可以在 Python 3.0 中简单地做到这一点:

      def bits_on_count(x):
        return sum(c=='1' for c in bin(x))
      

      这使用了 bin(x) 给出 x 的二进制表示这一事实。

      【讨论】:

        【解决方案7】:

        试试这个模块:

        import sys
        if sys.maxint < 2**32:
            msb2= 2**30
        else:
            msb2= 2**62
        BITS=[-msb2*2] # not converted into long
        while msb2:
            BITS.append(msb2)
            msb2 >>= 1
        
        def bitcount(n):
            return sum(1 for b in BITS if b&n)
        

        这应该适用于机器整数(取决于您的操作系统和 Python 版本)。它不适用于任何long

        【讨论】:

          【解决方案8】:

          你觉得这个怎么样:

          def bitsoncount(x):
              b   = 0
              bit = 1
              while bit <= x:
                  b += int(x & bit > 0)
                  bit = bit << 1
          
              return b
          

          基本上,您使用的测试位从右开始并一直移动到您的 in 参数的位长度。对于每个位置,位 & x 产生一个打开或无的位。检查 > 0 并使用 int() 将结果 True|False 变为 1|0,并将其添加到累加器中。似乎很适合长期工作:-)。

          【讨论】:

            【解决方案9】:

            如何统计Python开头的1位个数3.10:https://docs.python.org/3/library/stdtypes.html#int.bit_count

            # int.bit_count()
            
            n = 19
            bin(n)
            # '0b10011'
            
            
            n.bit_count()    # <-- this is how
            # 3
            
            (-n).bit_count()
            # 3
            

            相当于(根据上面链接的页面),但比:

            def bit_count(self):
                return bin(self).count("1")
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-03-14
              • 1970-01-01
              • 1970-01-01
              • 2020-12-05
              • 1970-01-01
              • 2011-06-20
              相关资源
              最近更新 更多