Python中正整数的位长度

use*_*832 42 python bits bitcount

1 = 0b1 -> 1
5 = 0b101 -> 3
10 = 0b1010 -> 4
100 = 0b1100100 -> 7
1000 = 0b1111101000 -> 10
…
Run Code Online (Sandbox Code Playgroud)

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

Sil*_*ost 171

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

>>> a = 100
>>> a.bit_length()
7
Run Code Online (Sandbox Code Playgroud)

  • @EricWalker 当然可以。您可以在任何拥有该方法的对象上调用该方法。文字也不例外。您确实需要使用正确的语法:如果您编写“2.”,那么它是浮点文字,而不是后跟字段访问运算符的整数文字。放置一个空格 `2 .bit_length()` 或使用括号 `(2).bit_length()`。 (14认同)
  • 奇怪的是,你不能对整数文字调用“bit_length()”。 (2认同)
  • 您也可以在 python 3 中使用 bit_length() 方法! (2认同)

YOU*_*YOU 23

>>> len(bin(1000))-2
10
>>> len(bin(100))-2
7
>>> len(bin(10))-2
4
Run Code Online (Sandbox Code Playgroud)

注意:对于负数不起作用,可能需要减去3而不是2

  • 更重要的是,这对于"0"来说是失败的. (3认同)
  • 虽然这不适用于负数(虽然它也不会失败,与日志版本相反) (2认同)
  • 如果你关心负数,那就做`len(bin(abs(n))) - 2` (2认同)

Gil*_*il' 6

如果您的 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
Run Code Online (Sandbox Code Playgroud)

一次移动整个单词,然后返回并处理最后一个单词的位,速度要快得多(至少对于大数字 - 快速基准测试表明对于 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
Run Code Online (Sandbox Code Playgroud)

在我的快速基准测试中,len(bin(n))结果甚至比字大小的块版本要快得多。尽管bin(n)构建了一个立即丢弃的字符串,但由于有一个编译为机器代码的内部循环,它会出现在最前面。(math.log甚至更快,但这并不重要,因为它是错误的。)


Dan*_*olo 0

def bitcounter(n):
    return math.floor(math.log(n,2)) + 1
Run Code Online (Sandbox Code Playgroud)

编辑已修复,使其适用于 1

  • 对于 2 的幂,这会减少 1。 (2认同)
  • @MarkDickinson:`math.log(n, 2)` 没有给出完全正确的结果。例如,`math.log(2**29, 2)` = 29.000000000000004。 (2认同)
  • @endolith:是的;我摸不着头脑,试图弄清楚当我写下这条评论时我到底在想什么。FWIW,Python 3 有“math.log2”,它*确实*给出了 2 的精确幂的浮点数的精确结果。 (2认同)
  • @endolith:有趣的是,在我的机器上,对于所有非负“n”,我得到“log(2**n, 2) >= n”,因此“math.floor(math.log(n, 2)” ) + 1` 仍然给出 2 次幂的正确结果。当然,对于所有 `n` 来说,虽然不是这样;`n = 2**48 - 1` 似乎是失败的最小值。 (2认同)