阶乘长度计算代码异常及十亿级大数阶乘求解问题咨询
解决阶乘位数计算问题(含十亿级大数方案)
嘿,我来帮你搞定这个问题!你的代码有几个关键问题,而且要处理十亿级的阶乘位数,直接计算阶乘完全不现实——咱们得换个思路用数学方法来解决。
你的代码存在的问题
咱们先拆解下你当前代码的问题:
- 缓存参数拼写错误:
@lru_cache(Maxsize = None)里的Maxsize应该是小写的maxsize,Python参数名大小写敏感,这会导致缓存根本没生效,递归时会重复计算(不过就算缓存生效了,后面的问题依然致命)。 - 递归深度限制:Python默认的递归深度只有约1000层,要计算十亿的阶乘,递归直接会触发
RecursionError,栈直接炸了,根本跑不到那么深。 - 内存爆炸问题:十亿的阶乘是个天文数字——它的位数大约有85亿位!你根本不可能把这个数存在内存里,更别说转成字符串求长度了,这完全不现实。
正确的解决方案:用数学公式计算阶乘位数
我们不需要实际计算阶乘,利用对数的性质就能快速算出阶乘的位数:
对于任意正整数n,n!的位数等于 floor(log₁₀(n!)) + 1。而log₁₀(n!)等于从1到n所有整数的log₁₀值之和,或者用斯特林近似公式(适合超大数)来快速估算。
方案1:累加对数法(适合中等规模的n)
这个方法通过累加每个数的log₁₀值来计算,比直接算阶乘高效得多,内存占用极低:
import math def factorial_digit_count(n): if n in (0, 1): return 1 total_log = 0.0 for k in range(1, n + 1): total_log += math.log10(k) return int(total_log) + 1
方案2:斯特林近似法(适合十亿级的超大数)
斯特林公式可以近似计算n!的对数,几乎是O(1)的计算速度,瞬间就能得出结果,完全不会有性能或内存问题:
import math def factorial_digit_count_stirling(n): if n in (0, 1): return 1 # 斯特林近似的对数形式 approximation = n * math.log10(n / math.e) + 0.5 * math.log10(2 * math.pi * n) return int(approximation) + 1
验证示例
比如计算5!的位数(5!是120,位数为3):
print(factorial_digit_count(5)) # 输出3 print(factorial_digit_count_stirling(5)) # 输出3
计算10!的位数(10!是3628800,位数为7):
print(factorial_digit_count(10)) # 输出7 print(factorial_digit_count_stirling(10)) # 输出7
对于十亿的情况,直接调用factorial_digit_count_stirling(10**9)就能瞬间得到结果,完全不用怕性能问题。
如果你只是想修复小范围的递归代码
如果只是想让代码在小n时正常运行,那要做两个修改:
- 把
Maxsize改成maxsize,让缓存生效; - 把递归改成迭代(避免栈溢出),不过即使这样,也只能处理很小的n(比如n<1000),因为实际计算阶乘的内存开销还是太大:
from functools import lru_cache @lru_cache(maxsize=None) def count(n): if n == 1: return 1 # 注意:这个逻辑还是会计算实际阶乘,只适合极小的n factorial_num = n * 10 ** count(n-1) # 仅为演示小范围修复,实际不如用数学方法 return len(str(factorial_num))
内容的提问来源于stack exchange,提问作者Anmol Gautam
相关产品推荐
相关产品推荐

