x=len(str(2**1000000000))
print(x)
我觉得这很有趣但是我的电脑开始滞后而且反应迟钝,到底发生了什么?
答案 0 :(得分:3)
在Python中,通常在整数世界中的计算是以任意大小完成的。所以这意味着如果你计算2**1000000000
,它将不会使用32位整数或64位整数,但它在Python-2.x中使用long
,或者Python-3.x中的int
(但Python-3.x中的int
)具有仲裁大小。
2**1000000000
是一个巨大的数字。它至少需要1'000'000'000位或125'000'000字节。它还将使用算法计算功率,并且还必须表示中间结果。
在CPython中,它需要133 MB的内存来存储值。但这不是结束。现在您要将其转换为字符串。该字符串将占用大约301'029'995位。每个数字至少占用一个字节。所以这需要额外的301 MB内存,而且需要大量的工作来计算十进制表示:每次迭代,我们必须执行模10检查,而且我们需要将数字除以10,所以它(至少)数字的位数是二次的。由于位数很大(约3亿),因此需要大量的工作。
len(..)
操作并不是非常昂贵,但上述步骤在内存中都很昂贵(并且CPU时间也很短,特别是转换为字符串)。内存似乎是我们可以忽略的一个因素,但是如果我们消耗大量内存,系统可能会变慢甚至冻结。通常,如果系统耗尽RAM内存,它将开始使用交换内存:它会将部分RAM内存换成硬盘驱动器,非常慢(与RAM内存相比)。
上面描述的获取位数的方法绝对不是一个好的方法。例如,它也不适用于负数。有一个名为 logarithms 的数学概念,如果你取一个数字的 log 10 ,你得到的数字减去一个。这里还有一些额外的问题:
log10
未定义;和log10
也不是零。但我们可以解决这些问题。例如,通过构建函数:
from math import log10, floor
def number_of_digits(x):
if x == 0:
return 1
else:
return 1 + floor(log10(abs(x)))
这适用于所有整数值。如果您想计算功率的位数,我们甚至可以阻止首先计算2**1000000000
:
from math import log10, floor
def number_of_digits_power(x, y):
return 1 + floor(y * log10(x))
所以位数是:
>>> number_of_digits_power(2, 1000000000)
301029996
这在速度和记忆方面都有效。
答案 1 :(得分:2)
您正在描述内存耗尽的典型反应。您的操作系统开始分页内存并将其写入硬盘驱动器(请参阅Virtual Memory)。如果您的虚拟内存被分页到旋转的硬盘驱动器,您的计算机将变得特别慢。任何尝试在其内存被分页后运行的程序都必须从磁盘读取内存,这是一个非常缓慢的过程。但是,继续占用更多内存的主程序仍在运行,因此所有其他进程都会因为剩下的内存很少而争吵。即使是正常的文件I / O也会因为存储忙于虚拟内存而变慢。这种无休止的内存分页是你的计算机如此慢的原因。
正如其他人在评论中提到的那样,计算和存储2**1000000000
本身并不需要大量的CPU或内存。这是你将整数转换为占用所有内存的字符串。您可以通过运行以下来验证这一点:
x = 2**1000000000
当您以这种方式将字符串分配给变量时,不应该转换为字符串。