编辑:问题解决了,但是从下面的代码中睁大眼睛,哈哈,从一开始我就有一些概念错误。
我已经尝试了比我更愿意承认计算各种32位整数中的非零位的时间,但总是看起来有点偏。
例如,数字的正数非零位数:
13676 9190872 136669 -17621 -1631 -183 15570 0 495 468656377 -1340216 -91
将是:
8 12 10 26 25 27 8 0 8 18
然而,无论我尝试什么,我总是至少在几个(尤其是负数)上最后几位数。
目前我正在使用:
def bitCount():
numbers = input().split()
answer = []
for num in numbers:
data = bin(((1 << 32) + int(num)) & -5)
bitCount = 0
for char in data[3:]:
if char == '1':
bitCount += 1
answer.append(str(bitCount))
print(' '.join(answer))
bitCount()
上述数字组合生成:7 12 9 25 24 26 8 0 7 18 19 26
我做错了什么?我该如何解决这个问题?我无法想象它太复杂了,但经过几个小时的搜索,阅读和试验,我觉得我必须错过一些明显的东西。任何帮助将不胜感激。
答案 0 :(得分:3)
你的整个方法在Python中没有意义。
-17621中的1
位数,即-100010011010101二进制,为7.如果您期望26,那么您不会要求1
位的数量在数字中,您要求C 32位2的补码有符号整数表示中的1
位数被解释为C 32位无符号整数。如果你想在Python中使用它,你必须明确地要求它。例如,您可以使用num % 0x100000000
。
与此同时,无论你从(1 << 32) + num & -5
获得了什么比特错误的技巧,它的也假设C int32数学而不是实际的整数算术,所以它&#39;再次出错了。另外,我很确定你错了。另外,没有理由在Python中使用这些技巧 - 实际上它实际上是慢,而不是更快,但无论哪种方式,它都会变得太慢,无论如何在一个紧密的循环中做了数十万次,而且速度超过了几次,所以这种挤出最后5%的优化在Python中比在C中更加毫无意义。(尽管其中很多使用现代编译器和CPU时,旧技巧实际上也减慢了C的速度......)
通过再次执行1
来取消初始[3:]
位假设您已经获得了32位表示,这也是错误的。 (那就是为什么你所有的正数都被1 - 你从第一个位置击倒了。)
所以,让我们简单一点:
answer = []
for num in numbers:
data = int(num) % 0x100000000
bits = format(data, 'b')
answer.append(str(bits.count('1')))
print(' '.join(answer))
请注意,我使用了format(data, 'b')
,所以我不必在开头就敲掉0b
。
或者,如果你想让它更紧凑:
print(' '.join(str(format(int(num)%0x100000000, 'b').count('1')) for num in numbers))
不管怎样,你得到:
8 12 10 26 25 27 8 0 8 18 20 28
...确实有两个数字而不是预期的输出,但是你输入的数字还比预期输出多两个,所以我认为这是预期的。
答案 1 :(得分:1)
试试这个:
#!/usr/bin/env python
def bit_counter(number):
suffix = 2
if number < 0:
suffix = 3
bit = bin(number)
counter = 0
for i in bit[suffix:]:
if int(i) == 1:
counter += 1
return counter
def main():
a = 13676
print bit_counter(a)
a = -13676
print bit_counter(a)
if __name__ == "__main__":
main()
适用于负数和非负数。
答案 2 :(得分:0)
整数中设置为1的位数称为汉明重量或人口数。
有几种 fast 算法可以执行此类计算。看看以下来源:
我首选的通用算法是:
def bit_count(n):
"""Return the number of bits set to 1 in the integer number 'n'.
This is called the Hamming weight or the population count of 'n'.
The algorithm performs as many iterations as there are set bits.
References:
The C Programming Language 2nd Ed., Kernighan & Ritchie, 1988.
Peter Wegner in CACM 3 (1960), 322.
"""
assert n >= 0, 'Argument of bit_count() must be non-negative'
count = 0
while n:
n &= n - 1
count += 1
return count
对于32位非负整数,以下函数更快:
def bit_count_parallel_32(n):
"""Return the number of set bits (1) present in the integer number 'n'.
This algorithm accepts only 32-bit non-negative integer numbers.
"""
assert 0 <= n < 2**32, ('Argument of bit_count_parallel_32() must be '
'non-negative and less than %d (2**32)') % 2**32
n = n - ((n >> 1) & 0x55555555)
n = (n & 0x33333333) + ((n >> 2) & 0x33333333)
return (((n + (n >> 4) & 0x0F0F0F0F) * 0x01010101) & 0xffffffff) >> (8 + 16)
如果有人需要它,这里是64位非负整数的版本:
def bit_count_parallel_64(n):
"""Return the number of set bits (1) present in the integer number 'n'.
This algorithm accepts only 64-bit non-negative integer numbers.
"""
assert 0 <= n < 2**64, ('Argument of bit_count_parallel_64() must be '
'non-negative and less than %d (2**64)') % 2**64
n = n - ((n >> 1) & 0x5555555555555555)
n = (n & 0x3333333333333333) + ((n >> 2) & 0x3333333333333333)
return (((n + (n >> 4) & 0x0F0F0F0F0F0F0F0F) * 0x0101010101010101) \
& 0xffffffffffffffff) >> (8 + 16 + 32)
但请注意,所有这些算法都不适用于负整数。如果需要使用负数,可以使用前面的函数来计算负数的2补码表示中设置的位数,例如:
>>> bit_count(-3 & 0xFF)
7
另请参阅致力于这本伟大着作Hacker's Delight的网站。
答案 3 :(得分:0)
最简单的方法是使用gmpy
:
import gmpy
[gmpy.popcount(n & 0xFFFFFFFF) for n in numbers]
#>>> [8, 12, 10, 26, 25, 27, 8, 0, 8, 18, 20, 28]
与字符串操作相比,这也可能非常快。
另一种方法是使用Numpy:
import numpy
def count_bits_u32(u32):
u32 = (u32 & 0x55555555) + ((u32 & 0xAAAAAAAA) >> 1)
u32 = (u32 & 0x33333333) + ((u32 & 0xCCCCCCCC) >> 2)
u32 = (u32 & 0x0F0F0F0F) + ((u32 & 0xF0F0F0F0) >> 4)
u32 = (u32 & 0x00FF00FF) + ((u32 & 0xFF00FF00) >> 8)
u32 = (u32 & 0x0000FFFF) + ((u32 & 0xFFFF0000) >> 16)
return u32
count_bits_u32(numpy.array(numbers, dtype="uint32"))
#>>> array([ 8, 12, 10, 26, 25, 27, 8, 0, 8, 18, 20, 28], dtype=uint32)
对于大型值列表,这可能更有效,因为它打包整数并使用向量化操作。