在以给定精度计算Pi近似时,我遇到了问题。我得出结论,无限循环问题是由我的循环退出条件引起的,但我不知道确切的问题是什么。在我看来,退出条件应该是
abs(current_aproximation - previous_approximation) < precision
以下是代码:
let pi(prec) =
let rec loop(curr, prev) =
if(abs_float( (2. /. curr) -. (2. /. prev) ) < prec) then // problematic line
(2. /. curr)
else
loop(curr *. sqrt(2. +. curr) /. 2., curr)
in loop(sqrt(0.5), 1.);;
感谢有关解决问题的任何提示。
答案 0 :(得分:1)
如果您修改代码以打印出curr
的值,您会发现很快就会达到修复点:
9.88131291682e-324
9.88131291682e-324
9.88131291682e-324
9.88131291682e-324
9.88131291682e-324
9.88131291682e-324
9.88131291682e-324
9.88131291682e-324
9.88131291682e-324
(...)
根据Wikipedia,您的初始值应为(sqrt 2.) /. 2.
而不是sqrt (0.5)
。但即使进行了这种修改,也不可能在没有达到前面描述的固定点的情况下请求小于0.61
的精度。
我的猜测是float
s不够精确,无法用这种方式表达这种算法。
答案 1 :(得分:1)
您正在计算不同的产品:在一次迭代后,您应该计算sqrt(2)/ 2 * sqrt(2 + sqrt(2))/ 2,但您计算sqrt(2)/ 2 * sqrt(2+) SQRT(2)/ 2)/ 2。
这个算法怎么样?
let pi prec =
let rec p2 xn root =
let nroot = sqrt(2. +. root) in
let xm = xn *. (nroot /. 2.) in
if (abs_float (( 2. /. xm ) -. (2. /. xn))) < prec
then xm
else p2 xm nroot
in 2. /. (p2 1.0 0.0)
评估为:
# pi 0.1 ;;
- : float = 3.12144515225805197
# pi 0.01 ;;
- : float = 3.14033115695475251
# pi 0.001 ;;
- : float = 3.14127725093277288
# pi 0.0001 ;;
- : float = 3.14157294036709134