使用Viete公式计算Pi近似时,陷入ocaml中的无限循环

时间:2015-11-04 10:18:44

标签: ocaml pi approximation

在以给定精度计算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.);;

感谢有关解决问题的任何提示。

2 个答案:

答案 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