Skip to content

Instantly share code, notes, and snippets.

@komasaru
Last active April 19, 2018 05:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save komasaru/5243832 to your computer and use it in GitHub Desktop.
Save komasaru/5243832 to your computer and use it in GitHub Desktop.
Ruby script to calc pi by Klingenstierna formula.
#! /usr/local/bin/ruby
#*********************************************
# 円周率計算 by Klingenstierna の公式
#*********************************************
#
class CalcPiKlingenstierna
FNAME = "pi_klingenstierna.txt"
def initialize(x)
@l = x # 計算桁数
@l1 = (@l / 8) + 1 # 配列サイズ
@n = (@l + 1) / 2 + 1 # 計算項数
end
# 計算・結果出力
def calc
# 計算開始時刻
t0 = Time.now
# 配列宣言・初期化
s = Array.new(@l1 + 2, 0) # 総和
a = Array.new(@l1 + 2, 0) # Klingenstierna の公式の第1項
b = Array.new(@l1 + 2, 0) # Klingenstierna の公式の第2項
c = Array.new(@l1 + 2, 0) # Klingenstierna の公式の第3項
q = Array.new(@l1 + 2, 0) # Klingenstierna の公式の第1項+第2項+第3項
# Klingenstierna の公式
a[0] = 32 * 10
b[0] = 4 * 239
c[0] = 16 * 515
1.upto(@n) do |k|
a = long_div(a, 10 * 10)
b = long_div(b, 239 * 239)
c = long_div(c, 515 * 515)
q = long_sub(a, b)
q = long_sub(q, c)
q = long_div(q, 2 * k - 1)
unless k % 2 == 0
s = long_add(s, q)
else
s = long_sub(s, q)
end
end
# 計算終了時刻
t1 = Time.now
# 計算時間
tt = t1 - t0
# 結果出力
display(tt, s)
rescue => e
raise
end
private
# ロング + ロング
def long_add(a, b)
z = Array.new(@n, 0)
cr = 0
(@l1 + 1).downto(0) do |i|
z[i] = a[i] + b[i] + cr
if z[i] < 100000000
cr = 0
else
z[i] -= 100000000
cr = 1
end
end
return z
rescue => e
raise
end
# ロング - ロング
def long_sub(a, b)
z = Array.new(@n, 0)
br = 0
(@l1 + 1).downto(0) do |i|
z[i] = a[i] - b[i] - br
if z[i] >= 0
br = 0
else
z[i] += 100000000
br = 1
end
end
return z
rescue => e
raise
end
# ロング / ショート
def long_div(a, b)
z = Array.new(@n, 0)
r = 0
0.upto(@l1 + 1) do |i|
w = a[i]
z[i] = (w + r) / b
r = ((w + r) % b) * 100000000
end
return z
rescue => e
raise
end
# 結果出力
def display(tt, s)
puts "** Pi Computation with the Klingenstierna formula method **"
printf(" Digits = %d.\n", @l)
printf(" Time = %f seconds\n", tt)
# ファイル出力
out_file = File.open(FNAME, "w")
out_file.puts "** Pi Computation with the Klingenstierna formula method **"
out_file.printf(" Digits = %d.\n", @l)
out_file.printf(" Time = %f seconds.\n\n", tt)
out_file.printf(" %d.\n", s[0])
1.upto(@l1 - 1) do |i|
out_file.printf("%08d:", (i - 1) * 8 + 1) if (i % 10 == 1)
out_file.printf(" %08d", s[i])
out_file.printf("\n") if (i % 10 == 0)
end
printf("\n")
rescue => e
raise
end
end
if __FILE__ == $0
begin
print "Please input number of Pi Decimal-Digits : "
n = gets.to_i
# 計算クラスインスタンス化
obj = CalcPiKlingenstierna.new(n)
# 円周率計算
obj.calc
rescue => e
$stderr.puts "[#{e.class}] #{e.message}\n"
e.backtrace.each{ |tr| $stderr.puts "\t#{tr}" }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment