マチンの公式による円周率の計算
https://ja.wikipedia.org/wiki/マチンの公式
マチンの公式
計算
マチンの公式を
の形にし,arctan(x) をグレゴリー級数に直して,それぞれ最初の方の項だけを計算して差を取る。
wikipedia では 各項の和を取る範囲を違ったものにしているが,以下のプログラムでは同じにした。
また指定した桁が確保できるまで収束計算を続ける。収束までの反復回数は「0.72 * 指定桁」である(経験則で導いた)。
function machin(precision=15; trace=false)
if precision > 15
f1, f2, f4, f5, f16, f239, N = big(1), big(2), big(4), big(5), big(16), big(239), 0.72precision
setprecision(BigFloat, ceil(Int, precision/log10(2)))
else
f1, f2, f4, f5, f16, f239, N = 1, 2, 4, 5, 16, 239, 11
end
f1byf5 = f1 / f5
f1byf239 = f1 / f239
x1 = x2 = x = 0
for n in 0:N
alpha = f2 * n + f1
sig = iseven(n) ? f1 : -f1
x1 += f16 * sig / alpha * f1byf5 ^ alpha
x2 += f4 * sig / alpha * f1byf239 ^ alpha
new_x = x1 - x2
trace && println("$(n+1): $new_x")
x == new_x && return new_x
x = new_x
end
println("not converged!")
end
machin (generic function with 2 methods)
浮動小数点数 Float64 では 11 回の反復回数でほぼ正しい結果が得られる。
println(machin(trace=true))
println(1pi)
1: 3.18326359832636
2: 3.1405970293260603
3: 3.1416210293250346
4: 3.1415917721821773
5: 3.1415926824043994
6: 3.1415926526153086
7: 3.141592653623555
8: 3.1415926535886025
9: 3.141592653589836
10: 3.1415926535897922
11: 3.141592653589794
12: 3.141592653589794
3.141592653589794
3.141592653589793
指定した桁数より多めに計算されるが,結果はかなり正確である。
println(machin(50))
println(big(pi))
3.141592653589793238462643383279502884197169399375101
3.141592653589793238462643383279502884197169399375101
length("141592653589793238462643383279502884197169399375101")
51
20000 桁の計算では,末尾 4 桁が異なる。
@time a = machin(20000);
39.491599 seconds (1.91 M allocations: 11.740 GiB, 0.17% gc time)
println(string(a)[end-50:end])
296810620377657883716690910941807448781404907552024
println(string(big(pi))[end-50:end])
296810620377657883716690910941807448781404907551788
@time b = machin(20010);
39.650767 seconds (2.36 M allocations: 15.209 GiB, 0.22% gc time)
println(string(b)[end-50:end])
776578837166909109418074487814049075517820385654186