遊びで平方根(二乗根)を扱うクラス(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)
作っていてなかなか楽しかったです。