我想写一个函数来计算 (1/n!) * (1! + 2! + 3! + ... + n!) ,其中 n 作为函数的参数,结果也被截断为6 位小数(不四舍五入)。 下面是我的代码:
def going(n):
n1 = n
n2 = n
factorial = 1
back = 1
for i in range(2, n1+1):
factorial *= i
while n2>1:
this = 1
for i in range(2, n2+1):
this*=i
back+=this
n2 = n2-1
this = 1
result = int((1/factorial)*back*1000000)/1000000
return result
当我将参数 171 传递给函数时,我得到了以下回溯:
Traceback (most recent call last):
File "/Users/Desktop/going.py", line 18, in <module>
print(going(171))
File "/Users/Desktop/going.py", line 15, in going
result = int((1/factorial)*back*1000000)/1000000
OverflowError: int too large to convert to float
我该如何解决这个问题?非常感谢您的帮助!
--更新-- 抱歉,我没有澄清:我在 Codewars 中解决这个问题,我不认为我可以导入任何库来使用。因此,我需要一个可以避免使用任何库的解决方案。
Codewars 的原始问题:
考虑以下数字(其中 n! 是阶乘 (n)):
u1 = (1 / 1!) * (1!)
u2 = (1 / 2!) * (1! + 2!)
u3 = (1 / 3!) * (1! + 2! + 3!)
un = (1 / n!) * (1! + 2! + 3! + ... + n!)
谁会赢:1/n!或者(1!+ 2!+ 3!+ ... + n!)?
这些数字是否因为 1/n 而变为 0!还是因阶乘之和而趋于无穷大?
任务
对于给定的 n,计算 (1/n!) * (1! + 2! + 3! + ... + n!),其中 n 是大于或等于 1 的整数。
为避免四舍五入的讨论,返回截断到小数点后 6 位的结果,例如:
1.0000989217538616 将被截断为 1.000098 1.2125000000000001 将被截断为 1.2125
备注
请记住,阶乘增长相当快,您需要处理大量输入。
请您参考如下方法:
going(170) 按预期工作,对吗?
您看到的是计算机表示 float 的方式的基本限制,而不是 Python 本身 的问题。一般来说,大多数现代计算机使用 IEEE 754用非整数表示和执行数学运算。具体来说,数字使用 IEEE 754 的 "binary64" (double-precision)浮点表示的最大值为 2^1023 × (1 + (1 − 2^−52)),或大约 1.7976931348623157 × 10^308。原来是170! ≈ 7.2 × 10^306,刚好低于最大值。然而,171! ≈ 1.2 × 10^309,所以你运气不好。
在不遇到这些溢出错误或丢失精度的情况下实际执行大数字计算的最佳机会是使用像 gmpy2 这样的大数字库。 (参见 this previous answer)。一个可能的解决方案是:
from gmpy2 import mpz, add, div, fac
def going(n):
factorial = fac(n)
back = mpz(1)
for i in range(2, n+1):
back = add(back, fac(i))
result = div(back, factorial)
return result
