上一天,解决另一个Project Euler我在管理一个大的for i in range(n)
循环时遇到了麻烦。你知道吗
我观察到python
会抛出不同的错误,这取决于x
变量的大小。你知道吗
下面是一个mcve示例:
for i in range(x):
pass
其中:
如果x = 10**20
我得到了一个OverflowError
,
准确地说:OverflowError: range() result has too many items
。
否则如果x = 10**15
我得到了一个MemoryError
。
否则,如果x = 10**9
我得到了一个instant-system-freeze
我必须硬重置我的电脑。很少,我的电脑不是冻结,而是填满大约5GB的交换空间,变得非常慢。
我试图理解pythonbuilt-in exception的含义:
^{
Raised when the result of an arithmetic operation is too large to be represented. This cannot occur for long integers [...] and for most operations with plain integers, which return a long integer instead. [...]
这意味着整数不应该抛出这个异常;这个异常的原因是range()
有太多的项,所以我想10**15
也会抛出相同的异常,但是我得到了一个不同的异常。。。
^{
Raised when an operation runs out of memory but the situation may still be rescued (by deleting some objects). [...]
我应该删除哪个对象来挽救这种情况?它只是简单的退出,所以情况无法挽救。。。你知道吗
如果它觉得有太多的ram
使用,为什么它会用10**9
冻结我的电脑?
最后,我的问题是:
为什么我得到3个不同的结果,仅仅取决于x
变量中存储的值?
注意:
range(x)
将首先创建一个大小为x
的列表,然后用整数填充它。影响包括:x = 10**20
:OverflowError,因为列表只能容纳^{2**31 - 1
或2**63 - 1
)项。你知道吗x = 10**15
:MemoryError,因为内存不足,无法分配大小为x的(未初始化)列表x = 10**9
:将创建一个大小为x的列表;然后对于everyintegeri < x
,将创建一个新的int对象并将其写入磁盘;每个int对象都需要内存分配。(这最终可能会导致内存错误,也可能不会导致内存错误。)这会给CPU和内存带来很大的负载,从而降低机器的速度。你知道吗总之,对于前两种情况,对于python来说,任务显然无法完成,它引发了一个异常。在第三种情况下,它认为它可能能够完成任务,尽管速度很慢。你知道吗
嗯,
range
试图构建一个完整的列表,其中包含尽可能多的项x
。你知道吗对于死亡的即时交换,假设64位和一个固定的8字节整数,
x = 10**9
大约值8go。因此,如果您没有超过这一点(考虑到已经使用的RAM),您可以看到为什么系统交换。你知道吗再往下看,如果函数不能分配足够大的块来保存结果(在
10**15
的情况下,这个块看起来相当大),那么MemoryError
可能会被引发。你知道吗我不知道range
的实现细节,但它可能使用OverflowError
来确保元素的绝对最大数量(可能是为了防止MemoryError
,基于实际可用内存)。正如@ShadowRanger在注释中提到的,如果结果的长度不能放入
size_t
变量(2**31
(32位)或2**63
(64位))中,则会引发OverflowError
,因为它无法初始化这样的列表。你知道吗正如您所提到的,xrange没有这个问题,因为它不会生成整个列表,而是在每次迭代时生成一个值。这就是迭代器/生成器具有内存效率的原因。你知道吗
所以我快速看了一下,你可以看到为什么它抛出一个
OverflowError
。你知道吗相关问题 更多 >
编程相关推荐