1 = 0b1 -> 1
5 = 0b101 -> 3
10 = 0b1010 -> 4
100 = 0b1100100 -> 7
1000 = 0b1111101000 -> 10
…
如何获得整数的位长,即在 Python 中表示正整数所需的位数?
在 python 2.7+ 中有一个int.bit_length()
方法:
>>> a = 100
>>> a.bit_length()
7
>>> len(bin(1000))-2
10
>>> len(bin(100))-2
7
>>> len(bin(10))-2
4
注意:不适用于负数,可能需要减去 3 而不是 2
如果您的 Python 版本有它(Python 2 ≥2.7,Python 3 ≥3.1),请使用bit_length
标准库中的方法。
否则,len(bin(n))-2
正如您所建议的那样很快(因为它是用 Python 实现的)。请注意,这将为 0 返回 1。
否则,一个简单的方法是重复除以 2(这是一个简单的位移),并计算达到 0 需要多长时间。
def bit_length(n): # return the bit size of a non-negative integer
bits = 0
while n >> bits: bits += 1
return bits
一次移动整个单词,然后返回并处理最后一个单词的位,速度要快得多(至少对于大量数字而言——快速基准测试表明 1000 位的速度要快 10 倍以上)。
def bit_length(n): # return the bit size of a non-negative integer
if n == 0: return 0
bits = -32
m = 0
while n:
m = n
n >>= 32; bits += 32
while m: m >>= 1; bits += 1
return bits
在我的快速基准测试中,len(bin(n))
甚至比字大小的块版本快得多。尽管bin(n)
构建了一个立即丢弃的字符串,但由于有一个编译为机器代码的内部循环,它会出现在最前面。(math.log
甚至更快,但这并不重要,因为它是错误的。)
这里我们也可以使用切片。
对于正整数,我们从 2 开始:
len(bin(1)[2:])
len(bin(5)[2:])
len(bin(10)[2:])
len(bin(100)[2:])
len(bin(1000)[2:])
这将打印:
1
3
4
7
10
对于负整数,我们从 3 开始:
len(bin(-1)[3:])
len(bin(-5)[3:])
len(bin(-10)[3:])
len(bin(-100)[3:])
len(bin(-1000)[3:])
这将打印:
1
3
4
7
10
这是另一种方式:
def number_of_bits(n):
return len('{:b}'.format(n))
我想效率不高,但没有出现在以前的任何答案中......
def bitcounter(n):
return math.floor(math.log(n,2)) + 1
编辑已修复,以便它与 1 一起使用
如果可用,此解决方案会利用.bit_length()
,并回退到len(hex(a))
旧版本的 Python。它的优势bin
在于它创建了一个更小的临时字符串,因此它使用更少的内存。
请注意,它为 0 返回 1,但这很容易更改。
_HEX_BIT_COUNT_MAP = {
'0': 0, '1': 1, '2': 2, '3': 2, '4': 3, '5': 3, '6': 3, '7': 3}
def bit_count(a):
"""Returns the number of bits needed to represent abs(a). Returns 1 for 0."""
if not isinstance(a, (int, long)):
raise TypeError
if not a:
return 1
# Example: hex(-0xabc) == '-0xabc'. 'L' is appended for longs.
s = hex(a)
d = len(s)
if s[-1] == 'L':
d -= 1
if s[0] == '-':
d -= 4
c = s[3]
else:
d -= 3
c = s[2]
return _HEX_BIT_COUNT_MAP.get(c, 4) + (d << 2)
# Use int.bit_length and long.bit_length introduced in Python 2.7 and 3.x.
if getattr(0, 'bit_length', None):
__doc = bit_count.__doc__
def bit_count(a):
return a.bit_length() or 1
bit_count.__doc__ = __doc
assert bit_count(0) == 1
assert bit_count(1) == 1
assert bit_count(2) == 2
assert bit_count(3) == 2
assert bit_count(63) == 6
assert bit_count(64) == 7
assert bit_count(75) == 7
assert bit_count(2047) == 11
assert bit_count(2048) == 12
assert bit_count(-4007) == 12
assert bit_count(4095) == 12
assert bit_count(4096) == 13
assert bit_count(1 << 1203) == 1204
assert bit_count(-(1 << 1203)) == 1204
assert bit_count(1 << 1204) == 1205
assert bit_count(1 << 1205) == 1206
assert bit_count(1 << 1206) == 1207