Scheme 计算欧拉';OCaml的s常数

Scheme 计算欧拉';OCaml的s常数,scheme,ocaml,divide-by-zero,eulers-number,Scheme,Ocaml,Divide By Zero,Eulers Number,我今天开始学习OCaml。我已经知道Scheme,所以我想尝试将一些示例Scheme程序翻译成ML会很好。下面我有一些代码可以计算Euler数,但在OCaml中不起作用。我得到这个错误:Exception:Division\u by\u zero。我认为这可能是混合浮点和整数的问题。我还没有弄清楚如何为带有ocamldebug的函数设置断点。谁能确定我的错误发生在哪里?多谢各位 (定义(阶乘n) (如果(零?n)1(*n(阶乘(子1 nщщ)')) (定义(求e精度和) (如果(零精度)(加1和

我今天开始学习OCaml。我已经知道Scheme,所以我想尝试将一些示例Scheme程序翻译成ML会很好。下面我有一些代码可以计算Euler数,但在OCaml中不起作用。我得到这个错误:
Exception:Division\u by\u zero。
我认为这可能是混合浮点和整数的问题。我还没有弄清楚如何为带有
ocamldebug
的函数设置断点。谁能确定我的错误发生在哪里?多谢各位

(定义(阶乘n)
(如果(零?n)1(*n(阶乘(子1 nщщ)'))
(定义(求e精度和)
(如果(零精度)(加1和)
(find-e(sub1精度)(+sum(/1(阶乘精度‘‘‘‘‘)’))
(显示(格式为“~f”(find-e 100 0)))
设rec阶乘n=如果n==0,则1,否则n*阶乘(n-1);;
让rec找到精确的和=
如果精度==0
然后(和+1)
否则求e(精度-1)(和+(1/阶乘精度));;
设结果=find_e 100 0;;
我记得,scheme有一个“数字塔”,它试图防止您在数值计算中失去准确性

OCaml没有任何奇特的数字自动处理功能。您的代码使用的是类型
int
,它是一个固定大小的整数(在通常的实现中为31或63位)。因此,您的表达式
1/阶乘精度
在几乎所有情况下都将为0,
阶乘精度
的值对于除最小值以外的所有值都不可表示。
factorial 100
的值将是
0
,因为它是2^63的倍数:

# let rec fact n = if n < 2 then 1 else n * fact (n - 1);;
val fact : int -> int = <fun>
# fact 100;;
- : int = 0
如果我将其复制/粘贴到OCaml REPL(也称为“toplevel”)中,我会看到:

val factorial : float -> float = <fun>
val find_e : float -> float -> float = <fun>
val result : float = 2.71828182845904509
我记得,scheme有一个“数字塔”,它试图防止你们在数值计算中失去准确性

OCaml没有任何奇特的数字自动处理功能。您的代码使用的是类型
int
,它是一个固定大小的整数(在通常的实现中为31或63位)。因此,您的表达式
1/阶乘精度
在几乎所有情况下都将为0,
阶乘精度
的值对于除最小值以外的所有值都不可表示。
factorial 100
的值将是
0
,因为它是2^63的倍数:

# let rec fact n = if n < 2 then 1 else n * fact (n - 1);;
val fact : int -> int = <fun>
# fact 100;;
- : int = 0
如果我将其复制/粘贴到OCaml REPL(也称为“toplevel”)中,我会看到:

val factorial : float -> float = <fun>
val find_e : float -> float -> float = <fun>
val result : float = 2.71828182845904509

这个答案是对目前被接受的答案的补充

由于阶乘是整数值,因此使用浮点表示计算有点不幸,因为它会导致足够大的值的精度损失。Scheme和Lisp对bignum和ratio有一个透明的支持,但是OCaml有一个库来支持这一点

opam install zarith
然后在ocaml顶级中:

# #use "topfind";;
# #require "zarith";;
/home/user/.opam/4.11.0/lib/zarith: added to search path
/home/user/.opam/4.11.0/lib/zarith/zarith.cma: loaded
有两个主要模块,Z和Q(整数和有理数),以及一个用于旧的大整数模块的兼容性模块。您可能想看看文档:

库为整数定义自己的类型:

# Z.of_int(3);;
- : Z.t = <abstr>

同样,Q模块在计算分数时也有帮助。您可能可以通过这种方式在OCaml中实现代码的等效版本。

此答案是对当前公认答案的补充

由于阶乘是整数值,因此使用浮点表示计算有点不幸,因为它会导致足够大的值的精度损失。Scheme和Lisp对bignum和ratio有一个透明的支持,但是OCaml有一个库来支持这一点

opam install zarith
然后在ocaml顶级中:

# #use "topfind";;
# #require "zarith";;
/home/user/.opam/4.11.0/lib/zarith: added to search path
/home/user/.opam/4.11.0/lib/zarith/zarith.cma: loaded
有两个主要模块,Z和Q(整数和有理数),以及一个用于旧的大整数模块的兼容性模块。您可能想看看文档:

库为整数定义自己的类型:

# Z.of_int(3);;
- : Z.t = <abstr>

同样,Q模块在计算分数时也有帮助。您可能可以通过这种方式在OCaml中实现代码的等效版本。

您的意思是我应该将
int
的每个实例都更改为
float
?这样会更好,但100阶乘也不能表示为float。您还需要将运算符更改为使用float的运算符。我不认为这是家庭作业:-)所以我将编写一个使用float的版本。这是否意味着只有用于float的可选运算符?是的,OCaml是强类型的。给定的函数(如
+
)仅适用于一种类型的值(本例中为
int
)。添加浮点的运算符是
+。
(带尾随句点或小数点)。(我无法编辑上面的注释,但100阶乘实际上可以很好地表示为浮点。OCaml浮点(实际上是双精度)可以表示比我想象的更宽的范围。)您的意思是我应该将
int
的每个实例都更改为
float
?这样会更好,但100阶乘也不能表示为float。您还需要将运算符更改为使用float的运算符。我不认为这是家庭作业:-)所以我将编写一个使用float的版本。这是否意味着只有用于float的可选运算符?是的,OCaml是强类型的。给定的函数(如
+
)仅适用于一种类型的值(本例中为
int
)。添加浮点的运算符是
+。
(带尾随句点或小数点)。(我无法编辑上面的注释,但100阶乘实际上可以很好地表示为浮点。OCaml浮点(实际上是双精度)可以表示比我想象的更宽的范围。)