标准ML斐波那契溢出

时间:2016-10-04 22:05:23

标签: recursion functional-programming sml smlnj ml

我一直在搞乱学习一些功能性编程,并决定选择ML作为我的工具。自从我拿起ML之后的几天,也许已经花了大约5-6个小时来解决一些问题。无论如何,关于我的问题。

通常在学习语言时,我会通过一些项目的euler问题来了解语法和操作。所以我一直在研究一个需要阶乘功能的问题。虽然我一直遇到溢出错误,通常在其他语言中解决这个问题,我会添加一些memoization或依赖标准库来避免它,但我对ML的经验不足使得memoization看起来很陌生。

我尝试过使用尾递归但没有骰子的事情:

fun fact_helper (0,r:int) = r
| fact_helper (n:int,r:int) = fact_helper (n-1,n*r);

fun factorial n:int = fact_helper(n, 1);

即使使用标准库:

foldl op * 1 (List.tabulate(100, fn x => x + 1))

会导致溢出。

我做了一些谷歌搜索,但ML似乎有非常稀疏的讨论或社区。所以我想我的问题是什么是一个例子,或者我应该如何以memoized方式编写我的阶乘函数,或者一般如何避免ML中的溢出。

1 个答案:

答案 0 :(得分:6)

问题是你的实现依赖于Int.int数据类型,在SML / NJ上限制为31位(参见Int.precision)。这意味着您可以计算的值有一个上限。如果您试图超过该限制,您将获得Overflow例外:

- (Option.valOf Int.maxInt) + 1;

uncaught exception Overflow [overflow]
  raised at: <file stdIn>

解决方案是使用IntInf结构,它提供任意精度算术:

open IntInf;

fun fact_helper (0,r:int) = r
  | fact_helper (n:int,r:int) = fact_helper (n-1,n*r);

fun factorial n:int = fact_helper(n, 1);

factorial 50;
(* 30414093201713378043612608166064768844377641568960512000000000000 *)