Python 中正整数所需的最小位长度

发布于 2024-08-29 12:08:03 字数 173 浏览 5 评论 0原文

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

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

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

How can I get the bit length of an integer, i.e. the number of bits that are necessary to represent a positive integer in Python?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

吖咩 2024-09-05 12:08:03

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

>>> a = 100
>>> a.bit_length()
7

In python 2.7+ there is a int.bit_length() method:

>>> a = 100
>>> a.bit_length()
7
套路撩心 2024-09-05 12:08:03
>>> len(bin(1000))-2
10
>>> len(bin(100))-2
7
>>> len(bin(10))-2
4

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

>>> len(bin(1000))-2
10
>>> len(bin(100))-2
7
>>> len(bin(10))-2
4

Note: will not work for negative numbers, may be need to substract 3 instead of 2

唱一曲作罢 2024-09-05 12:08:03

如果您的 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 甚至更快,但这并不重要,因为它是错误的。)

If your Python version has it (≥2.7 for Python 2, ≥3.1 for Python 3), use the bit_length method from the standard library.

Otherwise, len(bin(n))-2 as suggested by YOU is fast (because it's implemented in Python). Note that this returns 1 for 0.

Otherwise, a simple method is to repeatedly divide by 2 (which is a straightforward bit shift), and count how long it takes to reach 0.

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

It is significantly faster (at least for large numbers — a quick benchmarks says more than 10 times faster for 1000 digits) to shift by whole words at a time, then go back and work on the bits of the last word.

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

In my quick benchmark, len(bin(n)) came out significantly faster than even the word-sized chunk version. Although bin(n) builds a string that's discarded immediately, it comes out on top due to having an inner loop that's compiled to machine code. (math.log is even faster, but that's not important since it's wrong.)

孤城病女 2024-09-05 12:08:03

这里我们也可以使用切片。

对于正整数,我们从 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

Here we can also use slicing.

For positive integers, we'd start from 2:

len(bin(1)[2:])
len(bin(5)[2:])
len(bin(10)[2:])
len(bin(100)[2:])
len(bin(1000)[2:])

which would print:

1
3
4
7
10

For negative integers, we'd start from 3:

len(bin(-1)[3:])
len(bin(-5)[3:])
len(bin(-10)[3:])
len(bin(-100)[3:])
len(bin(-1000)[3:])

which would print:

1
3
4
7
10
爱格式化 2024-09-05 12:08:03
def bitcounter(n):
    return math.floor(math.log(n,2)) + 1

编辑已修复,以便它适用于 1

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

EDIT fixed so that it works with 1

清欢 2024-09-05 12:08:03

这是另一种方式:

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

我认为效率不高,但没有出现在以前的任何答案中......

Here is another way:

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

Not so efficient I suppose, but doesn't show up in any of the previous answers...

会发光的星星闪亮亮i 2024-09-05 12:08:03

此解决方案利用 .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

This solution takes advantage of .bit_length() if available, and falls back to len(hex(a)) for older versions of Python. It has the advantage over bin that it creates a smaller temporary string, so it uses less memory.

Please note that it returns 1 for 0, but that's easy to change.

_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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文