x=len(str(2**1000000000))
print(x)
我觉得这很有趣,但我的电脑开始卡顿并且没有响应,到底发生了什么?
请您参考如下方法:
在 Python 中,整数世界中的计算通常以任意大小完成。所以这意味着,如果您计算 2**1000000000,它不会使用 32 位整数或 64 位整数来执行此操作,而是使用 long在 Python-2.x 中,或 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 内存相比)。
上面简略的获取位数的方法肯定不是什么好方法。例如,它也不适用于负数。有一个数学概念叫做对数,如果你取一个数的log10,你得到的位数是减去一个。这里还有一些额外的问题:
- 负数的
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
这在速度和内存方面都很有效。
