简体   繁体   English

n ** n ** n启发式Python

[英]n**n**n heuristics in Python

I just play around with Python and found just interesting thing: my computer (i5, 3 GHz) just hang out after several hours of attempting to compute 10 ** 10 ** 10 . 我只是玩Python并发现了一件有趣的事情:我的电脑(i5,3 GHz)在试图计算10 ** 10 ** 10几个小时后才挂出。 I know Math isn't a purpose Python was created for, but I wonder isn't there a way to help Python to compute it. 我知道Math不是为Python创建的目的,但我想知道是不是有办法帮助Python计算它。

What I have so far is my observation: n ** (2** lg(n**n)) works 2 times faster then n ** n ** n 到目前为止我所观察到的是: n ** (2** lg(n**n))n ** n ** n快2倍

n = 8 ** (8 ** 8)
n2 = 8 ** (2 ** 24)
# measured by timeit
> 4.449993866728619e-07
> 1.8300124793313444e-07

1) Does anyone have an idea how to solve n ** n ** n in a most sophisticated way? 1)有没有人知道如何以最复杂的方式解决n ** n ** n

2) Do generators can help in order to minimize memory abuse? 2)生成器可以帮助减少内存滥用吗?

10 ** 10 ** 10 is a very very large number . 10 ** 10 ** 10是一个非常大的数字 Python is trying to allocate enough memory to represent that number. Python正在尝试分配足够的内存来表示该数字。 10.000.000.000 (10 billion) digits takes a lot more memory than your computer can provide in one go, so your computer is now swapping out memory to disk to make space, which is why things are now so very very slow. 10.000.000.000(100亿)位数比计算机一次性提供的内存要多得多,因此您的计算机现在将内存交换到磁盘以腾出空间,这就是为什么现在的速度非常慢。

To illustrate, try using sys.getsizeof() on some numbers that do fit: 为了说明,尝试在一些适合的数字上使用sys.getsizeof()

>>> import sys
>>> sys.getsizeof(10 ** 10 ** 6)
442948
>>> sys.getsizeof(10 ** 10 ** 7)
4429264

so an additional digit requires roughly 10 times more memory. 所以额外的数字需要大约 10倍的内存。 The amounts above are in bytes, so a 1 million digit number takes almost half a megabyte, 10 million digits takes 4 megabytes. 以上金额以字节为单位,因此100万位数字几乎占用半兆字节,1000万位数字占4兆字节。 Extrapoliting, your number would require 4 gigabytes of memory. 在Extrapoliting中,您的号码需要4 GB的内存。 It depends on your OS and hardware if Python will even be given that much memory. 这取决于你的操作系统和硬件,如果Python甚至会给予那么多的内存。

Python stores integers in increments of 30 bits on modern platforms; Python在现代平台上以30位的增量存储整数; so every 30 bits requires an additional 4 bytes of storage. 所以每30位需要额外的4个字节的存储空间。 For 10 billion digits that comes down to (log2(10 ** 10 ** 10) / 30 * 4) / (1024 ** 3) == about 4.125GiB. 对于100亿个数字(log2(10 ** 10 ** 10) / 30 * 4) / (1024 ** 3) ==约4.125GiB。

You can't use Python to represent numbers this large. 你不能使用Python来表示这么大的数字。 Not even floating point numbers can reach that high: 甚至浮点数也不会达到那么高:

>>> 10.0 ** 10 ** 10
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: (34, 'Result too large')

I'm not that familiar with bignum (big number) handling in Python; 我对Python中的bignum(大数字)处理并不熟悉; perhaps the gmpy libray has facilities to represent such numbers that are better. 也许gmpy libray有能力代表更好的数字。

If integer precision is not of utmost importance, you could use float numbers 如果整数精度不是最重要的,则可以使用float

>>> 3**3**3
7625597484987
>>> 3.**3.**3.
7625597484987.0

However, for larger values those will quickly reach their limits: 但是,对于较大的值,这些将很快达到其极限:

>>> 5.**5.**5.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: (34, 'Numerical result out of range')

You can get much higher with decimal : decimal可以得到更高的值:

>>> import decimal
>>> d = decimal.Decimal
>>> d(5)**d(5)**d(5)
Decimal('1.911012597945477520356404560E+2184')
>>> d(10)**d(10)**d(8)
Decimal('1.000000000000000000000000000E+100000000')

By default, even those can not represent 10**10**10 : 默认情况下,即使是那些也不能代表10**10**10

>>> d(10)**d(10)**d(10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/decimal.py", line 2386, in __pow__
    ans = ans._fix(context)
  File "/usr/lib/python2.7/decimal.py", line 1676, in _fix
    ans = context._raise_error(Overflow, 'above Emax', self._sign)
  File "/usr/lib/python2.7/decimal.py", line 3872, in _raise_error
    raise error(explanation)
decimal.Overflow: above Emax

But those limits are not fixed. 但这些限制并不固定。 Using getcontext() you can make them as big as you want: 使用getcontext()可以使它们尽可能大:

>>> decimal.getcontext().Emax = 1000000000000
>>> d(10)**d(10)**d(10)
Decimal('1.000000000000000000000000000E+10000000000')

But remember that those numbers are not 100% precise to the last digit (your computer probably does not even have enough memory to store each digit), so don't be surprised if this happens: 但请记住,这些数字并不是最后一位数字的100%精确度(您的计算机可能甚至没有足够的内存来存储每个数字),所以如果发生这种情况,请不要感到惊讶:

>>> d(10)**d(10)**d(10) == d(10)**d(10)**d(10) + 1000000
True

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM