获取Python中整数所需的字节大小

Posted

技术标签:

【中文标题】获取Python中整数所需的字节大小【英文标题】:Get size in Bytes needed for an integer in Python 【发布时间】:2012-12-29 01:59:17 【问题描述】:

如何找出某个整数占用的存储字节数?

例如对于

十六进制 \x00 - \xff(或十进制 0 - 255 = 二进制 0000 0000 - 1111 1111)我希望得到 1(字节), 十六进制 \x100 - \xffff(或十进制 256 - 65535 = 二进制 0000 0001 0000 0000 - 1111 1111 1111 1111)会给我 2(字节)

等等。

输入十六进制或十进制格式的任何线索?

【问题讨论】:

那么,-1 的正确答案是什么? 【参考方案1】:

除非您正在处理 array.arraynumpy.array - 大小总是有对象开销。而且由于 Python 自然地处理 BigInts,所以真的很难说...

>>> i = 5
>>> import sys
>>> sys.getsizeof(i)
24

所以在 64 位平台上,它需要 24 个字节来存储可以存储在 3 位中的内容。

但是,如果你这样做了,

>>> s = '\x05'
>>> sys.getsizeof(s)
38

所以不,不是真的 - 你得到了 object 定义的内存开销,而不是原始存储......

如果你再服用:

>>> a = array.array('i', [3])
>>> a
array('i', [3])
>>> sys.getsizeof(a)
60L
>>> a = array.array('i', [3, 4, 5])
>>> sys.getsizeof(a)
68L

然后你会得到所谓的正常字节边界,等等……等等……等等……

如果您只想存储“纯粹”的内容 - 减去对象开销,那么从 2.(6|7) 开始,您可以使用 some_int.bit_length() (否则只需将其移位,如其他答案所示),然后从那里开始工作

【讨论】:

顺便说一句,号码为5,除了您所说的所有其他内容之外,还有实习要处理。这意味着某些 Python 实现可能不会存储5 的完整对象,但它们会存储 5000 的完整对象。 @abarnert 我知道 - 但感谢您为其他人指出这一点 是的,我想你已经有足够的答案了;仅在评论中指出它比尝试在答案中详细解释它更容易...... 这在内存使用方面可能有些兴趣,但在文件中存储字节时无关紧要。一个字节的位长始终为 8。 是的,而且由于问题明确要求后者,我什至否决了这个答案;它没有回答问题,而且它的赞成票比正确的要多。【参考方案2】:
def byte_length(i):
    return (i.bit_length() + 7) // 8

当然,正如 Jon Clements 所指出的,这不是实际 PyIntObject 的大小,它有一个 PyObject 标头,并以最容易处理而不是最紧凑的方式将值存储为 bignum ,并且您必须在实际对象之上至少有一个指针(4 或 8 个字节),依此类推。

但这是数字本身的字节长度。这几乎可以肯定是最有效的答案,也可能是最容易阅读的答案。

或者ceil(i.bit_length() / 8.0) 更具可读性?

【讨论】:

谁对此投了反对票,请解释一下原因? (字节长度与位长度的关系是不是很明显,或者内置的bit_length方法是做什么的,或者其他什么?) 另外,如果您只是想假装拥有 16 位整数,而 Python 只是模拟这一点的工具,只需将其设为 return (i.bit_length() + 15) // 16return (i.bit_length() + 31) // 32 即可获得 32 位整数。正如@JonClemens 的回答所显示的那样,无论如何 Python 的大小都不同,这取决于您。 我猜反对票来自要求十六进制格式的整数的问题,而不是十进制格式的整数。我已要求现在编辑问题以涵盖十六进制和十进制格式,否则您的答案将不适合该问题。【参考方案3】:

你可以使用简单的数学:

>>> from math import log
>>> def bytes_needed(n):
...     if n == 0:
...         return 1
...     return int(log(n, 256)) + 1
...
>>> bytes_needed(0x01)
1
>>> bytes_needed(0x100)
2
>>> bytes_needed(0x10000)
3

【讨论】:

应该对0 进行测试,因为log 无法处理。 这也会扼杀负数 @slashdottir 字节值本身不能为负数。有符号整数是一个定义问题,通常通过反转位,同时将最高有效位用作指示符,这样可以为任何正负值留出一半的空间。 你是个天才。【参考方案4】:

通过使用简单的二元运算将所有使用的位每次移动超过 1 个字节,您可以看到存储一个数字需要多少字节。

可能值得注意的是,虽然这种方法非常通用,但它不适用于负数,并且只查看变量的二进制而不考虑它存储的内容。

a = 256
i = 0

while(a > 0):
    a = a >> 8;
    i += 1;

print (i)

程序的行为如下:

a 是二进制的0000 0001 0000 0000 循环的每次运行都会将其向左移动 8:

loop 1:
0000 0001 >> 0000 0000
0000 0001 > 0 (1 > 0)

loop 2:

0000 0000 >> 0000 0001
0000 0000 > 0 (0 > 0)

END 0 is not > 0

所以需要 2 个字节来存储数字。

【讨论】:

【参考方案5】:

在python命令提示符下,你可以使用函数的大小

**$ import python 
$ import ctypes
$ ctypes.sizeof(ctypes.c_int)**

【讨论】:

不是发帖人要求的。 喜欢用 C 编写代码的人可能应该这样做,而不是在手头没有 Python 解决方案的所有事情上都使用 ctypes。【参考方案6】:
# Python 3

import math

nbr = 0xff                 # 255 defined in hexadecimal
nbr = "0:b".format(nbr)    # Transform the number into a string formated as bytes.

bit_length = len(nbr)      # Number of characters
byte_length = math.ceil( bit_length/8 ) # Get minimum number of bytes

【讨论】:

以上是关于获取Python中整数所需的字节大小的主要内容,如果未能解决你的问题,请参考以下文章

Python:如何从 4 字节字节数组中获取 4 字节大小的整数?

MySQL 的 float(24) 列所需的存储大小是多少?

我如何显示一个字节的位长,而不是整数

确定存储用户输入差异所需的最小字段大小的有效方法

如何将jpeg大小减小到“所需大小”?

获取字符串 只定宽度内 所需的高度 方法二