我正在编写一些代码来生成任意精度的数学常数 e(欧拉数)的数字。
from decimal import Decimal, getcontext
import decimal
s = 300_000
n = Decimal(1)
x = Decimal(1)
print("[+] Summing numbers...")
getcontext().prec = s
for i in range(s, 1, -1):
x *= i
n += x
result = (n / x) + Decimal(1.0)
它可以在 200k 次迭代或更少的情况下工作,但如果我将精度设置得更高,则会失败。
[+] Summing numbers...
Traceback (most recent call last):
File "D:\OneDrive\Desktop\PYTHON\py\trig\log\calc e\e1_2.py", line 12, in <module>
x *= i
decimal.Overflow: [<class 'decimal.Overflow'>]
>>>
如何使用 python 存储非常大的数字,即数十万位长,而不抛出小数。溢出错误?
我喜欢的另一种选择:使用普通的
int
,但按 10 的大幂缩放。例如,要用 100 位数字表示数字 1.0,请使用 10**100
。
使用类似的方法来计算欧拉数,计算下界(总是向下舍入)和上限(总是向上舍入),所以我知道它们公共前缀中的数字都是正确的:
from os.path import commonprefix
import sys
sys.set_int_max_str_digits(0)
lo = hi = add_lo = 10 ** 100_000
add_hi = -add_lo
i = 0
while add_lo:
i += 1
add_lo //= i
add_hi //= i
lo += add_lo
hi -= add_hi
digits = commonprefix([str(lo), str(hi)])
print('computed', len(digits), 'digits')
print('first digits:', digits[:10])
print('last digits:', digits[-10:])
输出,大约需要 4.5 秒(在线尝试!):
computed 99996 digits
first digits: 2718281828
last digits: 0797210042
如果您想要所有数字,请打印整个
digits
。
decimal
模块存在于decimal,即以10为基数的表示形式。对于任意精度数字的计算,请使用 int
和 fractions.Fraction
。
from fractions import Fraction
s = 300_000
x = 1
n = 1
for i in range(s, 1, -1):
x *= i
n += x
result = Fraction(n, x) + 1
# Display approximate value (the raw value is huge)
print(float(result)) # 2.718281828459045
你的问题是按计算顺序排列的。看看你的求和循环:
for i in range(300000, 1, -1):
x *= i
n += x
这会计算
300000!
(阶乘)——这就是溢出问题。您已超出小数包的最大值。
您需要研究所需值的连续近似值,而不是尝试除以两个巨大的数量。
或者,您可以切换到 Python 大整数。这会很慢,但你会得到结果。