为什么2⁶³的大小是36字节,而2⁶³-1只有24字节?
Why is the size of 2⁶³ 36 bytes, but 2⁶³-1 is only 24 bytes?
Python 中的一切都是对象。所以 Python 中的 int 大小会比平时大。
>>> sys.getsizeof(int())
24
好的,但为什么 2⁶³
与 2⁶³ - 1
相比需要多 12 个字节而不是一个字节?
>>> sys.getsizeof(2**63)
36
>>> sys.getsizeof(2**62)
24
我知道 2⁶³
是一个 long 而 2⁶³-1
是一个 int,但为什么相差 12 个字节?
没有更直观,我尝试了一些其他的东西:
>>> a = 2**63
>>> a -= 2**62
>>> sys.getsizeof(a)
36
a
仍然存储为 long,即使它现在可以在 int 中。所以这并不奇怪。但是:
>>> a -= (2**63 - 1)
>>> a = 2**63
>>> a -= (2**63 - 1)
>>> a
1L
>>> sys.getsizeof(a)
28
新尺寸。
>>> a = 2**63
>>> a -= 2**63
>>> a
0L
>>> sys.getsizeof(a)
24
变回24字节,但还是用了long。
我得到的最后一件事:
>>> sys.getsizeof(long())
24
问题:
内存存储在这些场景中如何工作?
子题:
为什么有 12 个字节的间隙来添加我们的直觉告诉我们只是 1 位?
为什么int()
和long()
是24字节,而long(1)
已经是28字节而int(2⁶²)
?
注意:Python 3.X 的工作方式有点不同,但并不更直观。这里我主要关注Python 2.7;我没有测试之前的版本。
虽然我没有在文档中找到它,但这是我的解释。
Python 2 隐含地将int
提升为long
,当值超过int中可以存储的值时。新类型 (long
) 的大小是 long
的默认大小,即 32。从现在开始,变量的大小将由它的值决定,它可以上升和上升下来。
from sys import getsizeof as size
a = 1
n = 32
# going up
for i in range(10):
if not i:
print 'a = %100s%13s%4s' % (str(a), type(a), size(a))
else:
print 'a = %100s%14s%3s' % (str(a), type(a), size(a))
a <<= n
# going down
for i in range(11):
print 'a = %100s%14s%3s' % (str(a), type(a), size(a))
a >>= n
a = 1 <type 'int'> 24
a = 4294967296 <type 'long'> 32
a = 18446744073709551616 <type 'long'> 36
a = 79228162514264337593543950336 <type 'long'> 40
a = 340282366920938463463374607431768211456 <type 'long'> 44
a = 1461501637330902918203684832716283019655932542976 <type 'long'> 48
a = 6277101735386680763835789423207666416102355444464034512896 <type 'long'> 52
a = 26959946667150639794667015087019630673637144422540572481103610249216 <type 'long'> 56
a = 115792089237316195423570985008687907853269984665640564039457584007913129639936 <type 'long'> 60
a = 497323236409786642155382248146820840100456150797347717440463976893159497012533375533056 <type 'long'> 64
a = 2135987035920910082395021706169552114602704522356652769947041607822219725780640550022962086936576 <type 'long'> 68
a = 497323236409786642155382248146820840100456150797347717440463976893159497012533375533056 <type 'long'> 64
a = 115792089237316195423570985008687907853269984665640564039457584007913129639936 <type 'long'> 60
a = 26959946667150639794667015087019630673637144422540572481103610249216 <type 'long'> 56
a = 6277101735386680763835789423207666416102355444464034512896 <type 'long'> 52
a = 1461501637330902918203684832716283019655932542976 <type 'long'> 48
a = 340282366920938463463374607431768211456 <type 'long'> 44
a = 79228162514264337593543950336 <type 'long'> 40
a = 18446744073709551616 <type 'long'> 36
a = 4294967296 <type 'long'> 32
a = 1 <type 'long'> 28
如您所见,类型在第一次变得对于 int
而言太大后仍保持 long
,初始大小为 32,但大小随值而变化(可以更高或低于 [或等于,显然] 到 32)
因此,为了回答您的问题,int
的基本大小为 24,long
的基本大小为 28,而 long
也有 space 用于节省大值(开始为 4 个字节 - 因此 long
为 32 个字节,但可以根据值上下移动)
至于您的 sub-question,为新数字创建唯一类型(具有唯一大小)是不可能的,因此 Python 具有 "sub classes" 类型 long
, 它处理一系列数字,因此,一旦你超过旧的限制 long
你必须使用更新的,它也占更大的数字,因此,它有几个字节。
why does it get 12 more bytes for 2⁶³ compared too 2⁶³ - 1 and not just one?
在 LP64 system1, a Python 2 int
consists of 正好三个 pointer-sized 件:
- 类型指针
- 引用计数
- 实际值,一个C
long int
总共 24 个字节。另一方面,Pythonlong
consists of:
- 类型指针
- 引用计数
- 位数,一个 pointer-sized 整数
- 值数字的内联数组,每个包含 30 位值,但以 32 位单元存储(其中一个未使用的位在加法和减法期间用于 efficient carry/borrow)
2**63需要64位来存储,所以3个30位的数字就够了。由于每个数字都是 4 个字节宽,所以整个 Python long
将占用 24+3*4 = 36 个字节。
换句话说,不同之处在于 long
必须单独存储数字的大小(8 个额外的字节),而 space-efficient 存储值(12 个字节)略少来存储 2**63) 的数字。包括大小,一个long
中的值2**63占20个字节。将其与简单 int
的 any 值占用的 8 个字节进行比较,得出观察到的 12 字节差异。
值得注意的是Python3只有一种整型,叫做int
,也就是variable-width,实现方式和Python2一样long
.
1
64 位 Windows 的不同之处在于它保留了 32 位 long int
,大概是为了与大量使用 char
、short
和 long
作为 8、16 和 32 位值的 "convenient" 别名,恰好在 16 位和 32 位系统上都可以工作。要在 x86-64 Windows 上获得实际的 64 位类型,必须使用 __int64
或(在较新的编译器版本上)long long
或 int64_t
。由于 Python 2 在内部依赖于 Python int
在各个地方适合 C long,因此 sys.maxint
仍然是 2**31-1
,即使在 64 位 Windows.这个怪癖在Python 3中也得到修复,它没有maxint.的概念
Python 中的一切都是对象。所以 Python 中的 int 大小会比平时大。
>>> sys.getsizeof(int())
24
好的,但为什么 2⁶³
与 2⁶³ - 1
相比需要多 12 个字节而不是一个字节?
>>> sys.getsizeof(2**63)
36
>>> sys.getsizeof(2**62)
24
我知道 2⁶³
是一个 long 而 2⁶³-1
是一个 int,但为什么相差 12 个字节?
没有更直观,我尝试了一些其他的东西:
>>> a = 2**63
>>> a -= 2**62
>>> sys.getsizeof(a)
36
a
仍然存储为 long,即使它现在可以在 int 中。所以这并不奇怪。但是:
>>> a -= (2**63 - 1)
>>> a = 2**63
>>> a -= (2**63 - 1)
>>> a
1L
>>> sys.getsizeof(a)
28
新尺寸。
>>> a = 2**63
>>> a -= 2**63
>>> a
0L
>>> sys.getsizeof(a)
24
变回24字节,但还是用了long。
我得到的最后一件事:
>>> sys.getsizeof(long())
24
问题:
内存存储在这些场景中如何工作?
子题:
为什么有 12 个字节的间隙来添加我们的直觉告诉我们只是 1 位?
为什么int()
和long()
是24字节,而long(1)
已经是28字节而int(2⁶²)
?
注意:Python 3.X 的工作方式有点不同,但并不更直观。这里我主要关注Python 2.7;我没有测试之前的版本。
虽然我没有在文档中找到它,但这是我的解释。
Python 2 隐含地将int
提升为long
,当值超过int中可以存储的值时。新类型 (long
) 的大小是 long
的默认大小,即 32。从现在开始,变量的大小将由它的值决定,它可以上升和上升下来。
from sys import getsizeof as size
a = 1
n = 32
# going up
for i in range(10):
if not i:
print 'a = %100s%13s%4s' % (str(a), type(a), size(a))
else:
print 'a = %100s%14s%3s' % (str(a), type(a), size(a))
a <<= n
# going down
for i in range(11):
print 'a = %100s%14s%3s' % (str(a), type(a), size(a))
a >>= n
a = 1 <type 'int'> 24
a = 4294967296 <type 'long'> 32
a = 18446744073709551616 <type 'long'> 36
a = 79228162514264337593543950336 <type 'long'> 40
a = 340282366920938463463374607431768211456 <type 'long'> 44
a = 1461501637330902918203684832716283019655932542976 <type 'long'> 48
a = 6277101735386680763835789423207666416102355444464034512896 <type 'long'> 52
a = 26959946667150639794667015087019630673637144422540572481103610249216 <type 'long'> 56
a = 115792089237316195423570985008687907853269984665640564039457584007913129639936 <type 'long'> 60
a = 497323236409786642155382248146820840100456150797347717440463976893159497012533375533056 <type 'long'> 64
a = 2135987035920910082395021706169552114602704522356652769947041607822219725780640550022962086936576 <type 'long'> 68
a = 497323236409786642155382248146820840100456150797347717440463976893159497012533375533056 <type 'long'> 64
a = 115792089237316195423570985008687907853269984665640564039457584007913129639936 <type 'long'> 60
a = 26959946667150639794667015087019630673637144422540572481103610249216 <type 'long'> 56
a = 6277101735386680763835789423207666416102355444464034512896 <type 'long'> 52
a = 1461501637330902918203684832716283019655932542976 <type 'long'> 48
a = 340282366920938463463374607431768211456 <type 'long'> 44
a = 79228162514264337593543950336 <type 'long'> 40
a = 18446744073709551616 <type 'long'> 36
a = 4294967296 <type 'long'> 32
a = 1 <type 'long'> 28
如您所见,类型在第一次变得对于 int
而言太大后仍保持 long
,初始大小为 32,但大小随值而变化(可以更高或低于 [或等于,显然] 到 32)
因此,为了回答您的问题,int
的基本大小为 24,long
的基本大小为 28,而 long
也有 space 用于节省大值(开始为 4 个字节 - 因此 long
为 32 个字节,但可以根据值上下移动)
至于您的 sub-question,为新数字创建唯一类型(具有唯一大小)是不可能的,因此 Python 具有 "sub classes" 类型 long
, 它处理一系列数字,因此,一旦你超过旧的限制 long
你必须使用更新的,它也占更大的数字,因此,它有几个字节。
why does it get 12 more bytes for 2⁶³ compared too 2⁶³ - 1 and not just one?
在 LP64 system1, a Python 2 int
consists of 正好三个 pointer-sized 件:
- 类型指针
- 引用计数
- 实际值,一个C
long int
总共 24 个字节。另一方面,Pythonlong
consists of:
- 类型指针
- 引用计数
- 位数,一个 pointer-sized 整数
- 值数字的内联数组,每个包含 30 位值,但以 32 位单元存储(其中一个未使用的位在加法和减法期间用于 efficient carry/borrow)
2**63需要64位来存储,所以3个30位的数字就够了。由于每个数字都是 4 个字节宽,所以整个 Python long
将占用 24+3*4 = 36 个字节。
换句话说,不同之处在于 long
必须单独存储数字的大小(8 个额外的字节),而 space-efficient 存储值(12 个字节)略少来存储 2**63) 的数字。包括大小,一个long
中的值2**63占20个字节。将其与简单 int
的 any 值占用的 8 个字节进行比较,得出观察到的 12 字节差异。
值得注意的是Python3只有一种整型,叫做int
,也就是variable-width,实现方式和Python2一样long
.
1 64 位 Windows 的不同之处在于它保留了 32 位
long int
,大概是为了与大量使用 char
、short
和 long
作为 8、16 和 32 位值的 "convenient" 别名,恰好在 16 位和 32 位系统上都可以工作。要在 x86-64 Windows 上获得实际的 64 位类型,必须使用 __int64
或(在较新的编译器版本上)long long
或 int64_t
。由于 Python 2 在内部依赖于 Python int
在各个地方适合 C long,因此 sys.maxint
仍然是 2**31-1
,即使在 64 位 Windows.这个怪癖在Python 3中也得到修复,它没有maxint.的概念