Skip to content

Instantly share code, notes, and snippets.

@komasaru komasaru/calc_pi_machin.rb
Last active Apr 19, 2018

Embed
What would you like to do?
Ruby script to compute Pi with Machin's formula.
#! /usr/local/bin/ruby
#*********************************************
# 円周率計算 by マチンの公式
#*********************************************
#
class CalcPiMachin
FNAME = "pi_machin.txt"
def initialize(x)
@l = x # 計算桁数
@l1 = (@l / 8) + 1 # 配列サイズ
n = (@l / Math::log10(1 / 5.0) - 1)
@n = (n / -2).truncate + 1 # 計算項数
end
# 計算・結果出力
def calc
# 計算開始時刻
t0 = Time.now
# 配列宣言・初期化
s = Array.new(@l1 + 2, 0) # 総和
a = Array.new(@l1 + 2, 0) # マチンの公式の前の項
b = Array.new(@l1 + 2, 0) # マチンの公式の後の項
q = Array.new(@l1 + 2, 0) # マチンの公式の前の項+後の項
# マチンの公式
a[0] = 16 * 5
b[0] = 4 * 239
1.upto(@n) do |k|
a = long_div(a, 5 * 5)
b = long_div(b, 239 * 239)
q = long_sub(a, b)
q = long_div(q, 2 * k - 1)
s = k % 2 == 0 ? long_sub(s, q) : long_add(s, q)
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 Machin 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 Machin 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 = CalcPiMachin.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
You can’t perform that action at this time.