平方根(ルート)を計算して遊ぶライブラリを作った(Ruby)

遊びで平方根(二乗根)を扱うクラス(Root)を Ruby で書いてみました。三乗根とかそれ以上は扱えません(笑)。

コードは下(Gist)にあります。
平方根の計算 · GitHub


オブジェクトの生成。Integer, Rational, Float のルートが扱えます。Root.new(n) または Root.new(a, b) でも、 Root(n) または Root(a, b) でもどちらでも OK です。分数(Rational)のルートを取った場合など、有理化は自動的になされます。Float の場合は to_r してルートを取ります。また、根号の外へ出せる数がある場合は自動的に外へ出します

$ pry
[1] pry(main)> require_relative "root"
=> true
[2] pry(main)> Root.new(3)
=> Root(3)
[3] pry(main)> Root(7, 3)
=> (7)Root(3)
[4] pry(main)> Root(1/3r)
=> (1/3)Root(3)
[5] pry(main)> Root(2.5)
=> (1/2)Root(10)
[6] pry(main)> Root(12)
=> (2)Root(3)
[7] pry(main)> Root(4)
=> (2)Root(1)

根号の中はかならず自然数であり、係数は整数あるいは分数(Rational)です。
 
係数と根号の中身を取り出すことができます。

[4] pry(main)> x = Root(12)
=> (2)Root(3)
[5] pry(main)> x.content
=> 3
[6] pry(main)> x.coefficient
=> 2

 
掛け算(*)、割り算(/)、累乗(**)ができます。マイナスの単項演算子が使えます。

[2] pry(main)> a = Root(3)
=> Root(3)
[3] pry(main)> a * Root(6)
=> (3)Root(2)
[4] pry(main)> a * Root(3)
=> 3
[5] pry(main)> a * Root(1/5r)
=> (1/5)Root(15)
[6] pry(main)> a / Root(6)
=> (1/2)Root(2)
[7] pry(main)> a * 5
=> (5)Root(3)
[8] pry(main)> (2/7r) * a
=> (2/7)Root(3)
[9] pry(main)> a / 1.5
=> (2/3)Root(3)
[10] pry(main)> a ** 2
=> 3
[11] pry(main)> a ** 3
=> (3)Root(3)
[12] pry(main)> 3 / a
=> Root(3)
[13] pry(main)> 2 ** a
=> 3.3219970854839125
[14] pry(main)> a ** 1.5
=> 2.2795070569547775
[15] pry(main)> -a
=> (-1)Root(3)

 
計算できる場合に限り、足し算と引き算ができます。

[2] pry(main)> a = Root(3)
=> Root(3)
[3] pry(main)> a + Root(12)
=> (3)Root(3)
[4] pry(main)> a - Root(3) * 2
=> (-1)Root(3)
[5] pry(main)> 4 + Root(9)
=> 7
[6] pry(main)> 3.0 - Root(4)
=> 1.0
[7] pry(main)> Root(2) + 3.0
=> 4.414213562373095
[8] pry(main)> a + Root(5)
TypeError: Root(5) (Class Root) can not be used at this place.
from /home/***/Documents/Ruby/root.rb:197:in 'error'
[9] pry(main)> 3 - Root(5)
TypeError: (-1)Root(5) (Class Root) can not be used at this place.
from /home/***/Documents/Ruby/root.rb:224:in `error'

 
比較ができます。定義されている演算子は、< > <= >= == <=> です。

[1] pry(main)> Root(5) > Root(3)
=> true
[2] pry(main)> Root(3) > 2
=> false
[3] pry(main)> Root(3) <= 2
=> true
[4] pry(main)> Root(4) == 2
=> true
[5] pry(main)> Root(5) == Root(3)
=> false
[6] pry(main)> Root(3) > 1.7
=> true
[7] pry(main)> 2 < Root(5)
=> true
[8] pry(main)> 3 <=> Root(10)
=> -1

 
なのでソートもできます。

[2] pry(main)> a = [3.0, -1, Root(3), Root(12), Root(1/5r), 6.5]
=> [3.0, -1, Root(3), (2)Root(3), (1/5)Root(5), 6.5]
[3] pry(main)> a.sort
=> [-1, (1/5)Root(5), Root(3), 3.0, (2)Root(3), 6.5]

 
プラスの単項演算子は、オブジェクトが整数なら Integer に変換します。そうでなければ self をそのまま返します。

[2] pry(main)> a = Root(4)
=> (2)Root(1)
[3] pry(main)> +a
=> 2
[4] pry(main)> +Root(5)
=> Root(5)

なお、計算をする場合はこの変換が自動でなされます。

Float への変換は to_f。Integer への変換 to_i は内部で to_f.to_i になります(小数点以下切り捨て)。Integer, Rational, Float からのオブジェクトの生成は to_root

[5] pry(main)> Root(7).to_f
=> 2.6457513110645907
[6] pry(main)> Root(7).to_i
=> 2
[7] pry(main)> 2.to_root
=> (2)Root(1)
[8] pry(main)> 1.5.to_root
=> (3/2)Root(1)

 
計算例。

[7] pry(main)> Root(6) * Root(1/3r) + 8 / Root(2)
=> (5/1)Root(2)
[8] pry(main)> Root(60) / Root(3/10r)
=> (10/1)Root(2)

 
例えばここのほとんどの計算ができます。

[2] pry(main)> Root(180)
=> (6)Root(5)
[3] pry(main)> Root(50) + Root(18)
=> (8)Root(2)
[6] pry(main)> Root(7, 3) - Root(27)
=> (4)Root(3)
[7] pry(main)> Root(5, 2) * Root(3, 2)
=> 30
[8] pry(main)> Root(4, 3) * Root(2, 5)
=> (8)Root(15)
[9] pry(main)> Root(4, 6) / Root(2, 2)
=> (2/1)Root(3)
[10] pry(main)> Root(4, 30) * Root(3, 21) / Root(6, 14)
=> (6/1)Root(5)
[11] pry(main)> 2 / Root(3)
=> (2/3)Root(3)
[12] pry(main)> Root(3) / Root(2, 7)
=> (1/14)Root(21)

 

作っていてなかなか楽しかったです。