Python中正整数的位长度

Bit length of a positive integer in Python

1
2
3
4
5
6
1 = 0b1 -> 1
5 = 0b101 -> 3
10 = 0b1010 -> 4
100 = 0b1100100 -> 7
1000 = 0b1111101000 -> 10

如何获取整数的位长度,即在python中表示正整数所需的位数?


在python 2.7+中,有一个int.bit_length()方法:

1
2
3
>>> a = 100
>>> a.bit_length()
7

1
2
3
4
5
6
>>> len(bin(1000))-2
10
>>> len(bin(100))-2
7
>>> len(bin(10))-2
4

注:对于负数无效,可能需要减去3而不是2。


如果您的python版本有它(≥2.7对于python 2,≥3.1对于python 3),请使用标准库中的bit_length方法。

否则,正如您建议的那样,len(bin(n))-2是快速的(因为它是在Python中实现的)。请注意,这将为0返回1。

否则,一个简单的方法是重复除以2(这是一个简单的位移位),并计算达到0所需的时间。

1
2
3
4
def bit_length(n): # return the bit size of a non-negative integer
    bits = 0
    while n >> bits: bits += 1
    return bits

它明显更快(至少对于大数字来说——一个快速的基准测试表明1000位数字的移动速度是10倍以上),一次按整个单词移动,然后返回并处理最后一个单词的位。

1
2
3
4
5
6
7
8
9
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更快,但这并不重要,因为它是错误的。)


另一种方法是:

1
2
def number_of_bits(n):
    return len('{:b}'.format(n))

我想效率不是很高,但在以前的回答中没有出现…


只需将值存储在一个变量中并访问它上面的bit_length()。在python 2和3中都可用。

1
2
n = 5
print(n.bit_length())

这个解决方案利用了.bit_length()(如果可用),而对于旧版本的python,则返回到len(hex(a))。与bin相比,它的优点是创建了一个较小的临时字符串,因此使用的内存更少。

请注意,它为0返回1,但这很容易更改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
_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


1
2
def bitcounter(n):
    return math.floor(math.log(n,2)) + 1

编辑Fixed,使其与1一起使用