APL求解Project Euler 20阶乘数字和遇大数报错如何解决
问题原因
常规APL实现默认使用64位整数或双精度浮点数存储数值,100!的数值约为9.3×10¹⁵⁷,远超过64位整数最大值(约9×10¹⁸),会被自动转换为科学计数法形式的浮点数。此时⍕(!100)输出的字符串包含小数点、字母e等非数字字符,传入执行函数⍎时就会触发语法错误。
解决方法
方法1:开启任意精度整数支持(适用于Dyalog APL等支持该特性的实现)
首先设置系统变量启用十进制任意精度:⎕FR←1287
同时可以优化原有代码,用字符编码偏移转换代替不安全的⍎操作(数字字符的Unicode编码比对应数值大48):+/ (⍕!100) - ⎕UCS 48
执行后即可得到100!各位数字之和的正确结果648。方法2:无大整数支持的逐位计算方案
如果所用APL实现不支持任意精度整数,可以通过模拟手工乘法的逻辑直接操作各位数字数组,全程不会生成超大数值:
∇ sum←SumFactDigits n digits←,1 ⍝ 初始化阶乘各位数组,初始值为1 :For k :In ⍳n digits←k×digits ⍝ 从低位到高位处理进位 carry←0 :For i :In ⌽⍳⍴digits total←digits[i]+carry digits[i]←10|total carry←⌊total÷10 :EndFor ⍝ 剩余进位补到高位 :While carry>0 digits←(10|carry),digits carry←⌊carry÷10 :EndWhile :EndFor sum←+/digits ∇
调用SumFactDigits 100即可得到正确结果648。
原有代码优化建议
- 不要使用
⍎¨转换数字字符,直接用字符编码偏移转换更高效、安全,可避免非数字字符导致的语法错误 - 计算超大阶乘前优先确认当前数值精度是否满足需求,或者直接使用逐位计算方案从根源避免溢出问题
内容的提问来源于stack exchange,提问作者user17356614
相关产品推荐
相关产品推荐

