オイラーの級数
http://commutative.world.coocan.jp/blog5/2021/09/post-431.html
計算時間を短縮するには,関数化する,ファイル入力しないの他,今回は,
関数に実際に渡されるものに特化した関数定義,引数の精度を見極める。
同じものを何度も計算しない(関数を呼ばない),p^3, p^5 を毎回計算するのは無駄(特に長精度計算の場合)。
ということで,元のプログラムを以下のように書き換えた。
using Primes
function SGN(p) # p は奇数に限られる。 p は Int64 で十分
if ((p - 1) ÷ 2) % 2 == 0
return -1
else
return 1
end
end
function h()
S1 = S2 = S3 = 0
for p0 in primes(3, 10^10) # 3 以上 10^10 未満の奇数素数が対象
s = SGN(p0)
p = Int128(p0)
S1 += s / p
p2 = p^2
S2 += s / (p*p2) # p^3, p^5 を別途計算するのは無駄
S3 += s / (p*p2*p2)
end
println("Z(1) = $S1")
println("Z(3) = $S2")
println("Z(5) = $S3")
end
@time h()
Z(1) = 0.33498102728650697
Z(3) = 0.03225247383350187
Z(5) = 0.003858069415480658
32.803606 seconds (87 allocations: 5.885 GiB, 0.02% gc time)
元のプログラムの実行時間は 1196.311773 秒だったので,40 倍速近い。
40 倍と言っても 20 分が 30 秒になるのは体感的に随分違う。