- 3 有理数クラスを動かす. 四則の他の演算も追加し, 浮動小数点では正確に行えない計算をさせる.
- 4 複素数クラスを動かす. 役に立つ計算をしてみる.
有理数クラスRatioと複素数クラスCompを定義しました。コードは巻末に示しました。 以下のように実行し、結果を得ました。
puts Ratio.new(2, 3) + Ratio.new(1, 3)
puts Ratio.new(4, 3) - Ratio.new(1, 3)
puts Ratio.new(3, 1) * Ratio.new(1, 3)
puts Ratio.new(1, 3) / Ratio.new(1, 3)
puts Comp.new(2, 3) + Comp.new(1, 3)
puts Comp.new(4, 3) - Comp.new(1, 3)
puts Comp.new(3, 1) * Comp.new(1, 3)
puts Comp.new(1, 3) / Comp.new(1, 3)
1/1
1/1
1/1
1/1
3 + 6i
3 + 0i
0 + 10i
1 + 0i
まず、Ratioクラスに対し、各四則演算と,@a, @bへのgetter関数c, dを定義しました。
名前をa, b, c, dと公式にあわせたり,*= などを用いることで、コードが読みやすくなりました。
また、例では各演算ごとにインスタンス化していて、最適化できていないと考えられるので、
initialize内にあった処理を別の関数bindにうつし、各演算ではselfを返すようにしました。
また、Compクラスの乗法、除法ではを直接代入すると値がおかしくなるので、
計算結果は変数a, bへ一旦代入し、あとから @a, @bを指定するようにしました。
class Ratio
def initialize(a, b=1)
@a = a
@b = b
self.bind
end
def bind
if @b == 0 then @a = 1; return end
if @a == 0 then @b = 1; return end
if @b < 0 then @a = -@a; @b = -@b end
g = gcd(@a.abs, @b.abs); @a = @a/g; @b = @b/g
return self
end
def c
return @a
end
def d
return @b
end
def to_s
return "#{@a}/#{@b}"
end
def +(r)
@a = @a*r.d + @b*r.c
@b *= r.d
return self.bind
end
def -(r)
@a = @a*r.d - @b*r.c
@b *= r.d
return self.bind
end
def *(r)
@a *= r.c
@b *= r.d
return self.bind
end
def /(r)
@a *= r.d
@b *= r.c
return self.bind
end
def gcd(x, y)
while true do
if x > y then x = x % y; if x == 0 then return y end
else y = y % x; if y == 0 then return x end
end
end
end
end
class Comp
def initialize(a, b=1)
@a = a
@b = b
end
def c
return @a
end
def d
return @b
end
def to_s
return "#{@a} + #{@b}i"
end
def +(r)
@a += r.c
@b += r.d
return self
end
def -(r)
@a -= r.c
@b -= r.d
return self
end
def *(r)
a = @a*r.c - @b*r.d
b = @b*r.c + @a*r.d
@a = a; @b = b
return self
end
def /(r)
a = (@a*r.c + @b*r.d) / (r.c**2 + r.d**2)
b = (@b*r.c + @a*r.d) / (r.c**2 + r.d**2)
@a = a; @b = b
return self
end
end