为什么我的电脑运行缓慢并且运行这个python程序没有响应?

时间:2017-12-17 18:28:10

标签: python

x=len(str(2**1000000000))
print(x)

我觉得这很有趣但是我的电脑开始滞后而且反应迟钝,到底发生了什么?

2 个答案:

答案 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 ,你得到的数字减去一个。这里还有一些额外的问题:

  1. 负数的log10 未定义;和
  2. log10也不是零。
  3. 但我们可以解决这些问题。例如,通过构建函数:

    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

当您以这种方式将字符串分配给变量时,不应该转换为字符串。