1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
| #! /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
|