我正在实现一个递归程序来计算Schroder序列中的某些值,我遇到了两个问题:
- 我需要计算程序中的调用次数
- 超过某个数字,程序会生成不正确的值(我认为这是因为数字太大(
这是代码:
let rec schroder n =
if n <= 0 then 1
else if n = 1 then 2
else 3 * schroder (n-1) + sum n 1
and sum n k =
if (k > n-2) then 0
else schroder k * schroder (n-k-1) + sum n (k+1)
当我试图返回元组(1.(时,函数sum
停止工作,因为它试图在类型为int * int
时返回int
;关于2.,当我执行schroder 15
时,它返回:-357364258
它应该何时返回3937603038
。
编辑:
首先感谢你的提示,其次,经过几个小时的努力,我终于创建了这个功能,现在我的问题是我很难安装zarith。我想我已经安装好了,但是。。
在终端中,当我执行
ocamlc -I +zarith test.ml
时,我得到一个错误,说Required module 'Z' is unavailable
。在做了
#load "zarith.cma";;
和#install_printer Z.pp_print;;
之后,我可以在utop中编译、运行函数,它就工作了。然而,我正在尝试实现一个Scanf.scanf
,这样我就可以打印序列的不同值。有了这句话,每当我尝试运行scanf时,我都没有机会写任何数字,因为我收到一条消息说'\n' is not a decimal digit
。
话虽如此,我很可能在打印值时也会遇到问题,因为我认为我无法用%d
打印这么大的数字。下面代码中的let r1,c1 =
就是我所说内容的一个示例。
以下是我使用的:
(function)
..
let v1, v2 = Scanf.scanf "%d %d" (fun v1 v2-> v1,v2);;
let r1,c1 = schroder_a (Big_int_Z.of_int v1) in
Printf.printf "%d %dn" (Big_int_Z.int_of_big_int r1) (Big_int_Z.int_of_big_int c1);
let r2,c2 = schroder_a v2 in
Printf.printf "%d %dn" r2 c2;
p.S.'r1'&'r2代表结果,c1和c2代表schroder递归函数的调用次数。
附言:因为我只是在测试,所以指纹写得不一样,但我甚至无法通过扫描,所以…
这是我第三次在StackOverflow上看到这个问题,所以我认为这是某种学校作业。因此,我只想发表一些评论。
-
OCaml没有内置名为
sum
的函数。如果这是你自己编写的函数,那么显而易见的建议是重写它,这样它就知道如何将你想要返回的元组相加。无论如何,这将是一种方法。 -
的确,OCaml中的int会发生溢出。如果你想计算更大的值;"大数字";包裹与现代OCaml一起使用的是Zarith(我已经链接到OCaml.org上的描述(
然而,解决此任务的其他人都没有提到溢出是一个问题。如果您只是求解可表示的OCaml int值,那么您就可以了。
3937603038
大于32位int
所能容纳的容量,因此会溢出。您可以改为使用int64
来修复此问题(直到溢出为止(。您必须使用int64
文字,使用L
后缀,以及来自Int64
模块的操作。这是您的代码转换为int64
:来计算值
let rec schroder n =
if n <= 0 then 1L
else if n = 1 then 2L
else Int64.add (Int64.mul 3L (schroder (n-1))) (sum n 1)
and sum n k =
if (k > n-2) then 0L
else Int64.add (Int64.mul (schroder k) (schroder (n-k-1))) (sum n (k+1))
我需要计算程序中的调用次数;。。。函数"sum"停止工作,因为当它具有类型"int*int"时,它正试图返回"int">
确保已更新对shroder
的所有递归调用。请记住,它现在返回的是一对,而不是一个数字,所以你不能只添加它,你需要先打开这对。例如,
...
else
let r,i = schroder (n-1) (i+1) in
3 * r + sum n 1 and ...
等等
超过某个数字,程序将生成不正确的值(我认为这是因为数字太大(;
您需要使用任意精度的数字,例如zarith