Python 对于 1 的左移和 2 的幂的行为不同
Python behaves differently for left shift of 1 and power of 2
我试图在我的系统上计算 1 << sys.maxsize
,python 立即给了我一个
内存错误但是当我尝试做 2 ** maxsize
python 开始计算它时没有任何内存错误。
尽管 1 << a 等同于 2 ** a。 (对于所有正 a)
为什么会有这种行为?
案例 1:
import sys
1 << sys.maxsize
案例 2:
import sys
2 ** sys.maxsize
案例 1 的结果:
---------------------------------------------------------------------------
MemoryError Traceback (most recent call last)
<ipython-input-41-0d82f9d0b2eb> in <module>()
----> 1 1 << sys.maxsize
MemoryError:
案例 2 的结果:
# This kept on going without any memory error
这两个操作在产生相同结果的方式上是等价的。
>>> import sys, math
>>> sys.maxsize, (sys.maxsize + 1) // 8, math.log((sys.maxsize + 1) // 8, 1024)
(9223372036854775807, 1152921504606846976, 6.0)
如上所示,2 个操作中的 none 是有意义的,因为(在 64 位 上)结果需要 1 EiB (exbibyte) 即 1048576 (> 一百万) TiB (tebibytes) !!!,所以它们都会 运行 内存不足。
根据[Python 3.docs]: Built-in Types - Numeric Types — int, float, complex:
Integers have unlimited precision.
在(C)源码中,Python的int 值表示为 unsigned short []
(longintrepr.h),这两个函数是 long_lshift 和long_pow ([GitHub]: python/cpython - (master) cpython/Objects/longobject.c).
这是 2 个函数的工作原理(简化版):
- lshift:尝试分配所需的字节来保存 final 结果 - 失败(几乎立即)
- pow:执行连续乘法,增加中间结果所需的space(你可以发出
2 ** sys.maxsize
并查看 任务管理器 中使用的内存如何增长,如果 Ctrl + Break 在 Python console,内存会下降)。
乘法是一种昂贵的(CPU 和时间方面的)操作(即使它有加速),还涉及内存分配/复制操作,所以给定足够的时间,中间结果会增长,直到它不适合最大的可用内存块,因此它会失败(有同样的错误)
我不确定为什么数字 2(作为基础),2nd 函数不只是简单地调用 1st 一个,但我想一个额外的 if 子句不会证明(它会引入所有其他数字的开销很小并且)没有人会/应该使用如此大的指数。
我试图在我的系统上计算 1 << sys.maxsize
,python 立即给了我一个
内存错误但是当我尝试做 2 ** maxsize
python 开始计算它时没有任何内存错误。
尽管 1 << a 等同于 2 ** a。 (对于所有正 a)
为什么会有这种行为?
案例 1:
import sys
1 << sys.maxsize
案例 2:
import sys
2 ** sys.maxsize
案例 1 的结果:
---------------------------------------------------------------------------
MemoryError Traceback (most recent call last)
<ipython-input-41-0d82f9d0b2eb> in <module>()
----> 1 1 << sys.maxsize
MemoryError:
案例 2 的结果:
# This kept on going without any memory error
这两个操作在产生相同结果的方式上是等价的。
>>> import sys, math >>> sys.maxsize, (sys.maxsize + 1) // 8, math.log((sys.maxsize + 1) // 8, 1024) (9223372036854775807, 1152921504606846976, 6.0)
如上所示,2 个操作中的 none 是有意义的,因为(在 64 位 上)结果需要 1 EiB (exbibyte) 即 1048576 (> 一百万) TiB (tebibytes) !!!,所以它们都会 运行 内存不足。
根据[Python 3.docs]: Built-in Types - Numeric Types — int, float, complex:
Integers have unlimited precision.
在(C)源码中,Python的int 值表示为 unsigned short []
(longintrepr.h),这两个函数是 long_lshift 和long_pow ([GitHub]: python/cpython - (master) cpython/Objects/longobject.c).
这是 2 个函数的工作原理(简化版):
- lshift:尝试分配所需的字节来保存 final 结果 - 失败(几乎立即)
- pow:执行连续乘法,增加中间结果所需的space(你可以发出
2 ** sys.maxsize
并查看 任务管理器 中使用的内存如何增长,如果 Ctrl + Break 在 Python console,内存会下降)。
乘法是一种昂贵的(CPU 和时间方面的)操作(即使它有加速),还涉及内存分配/复制操作,所以给定足够的时间,中间结果会增长,直到它不适合最大的可用内存块,因此它会失败(有同样的错误)
我不确定为什么数字 2(作为基础),2nd 函数不只是简单地调用 1st 一个,但我想一个额外的 if 子句不会证明(它会引入所有其他数字的开销很小并且)没有人会/应该使用如此大的指数。