平方根の計算
require 'prime' | |
module Kernel | |
def Root(*args) | |
Root.new(*args) | |
end | |
end | |
module ExRoot | |
def to_root | |
case self | |
when Float | |
rationalize.to_root | |
else | |
Root.new(self ** 2) | |
end | |
end | |
def *(ob) | |
case ob | |
when Root | |
ob * to_root | |
else | |
super(ob) | |
end | |
end | |
def /(ob) | |
case ob | |
when Root | |
1.to_root / ob * to_root | |
else | |
super(ob) | |
end | |
end | |
def **(ob) | |
case ob | |
when Root | |
self ** (ob.coefficient * Math.sqrt(ob.content)) | |
else | |
super(ob) | |
end | |
end | |
def +(ob) | |
case ob | |
when Root | |
case self | |
when Float | |
ob + self | |
else | |
(to_root + ob).int_check | |
end | |
else | |
super(ob) | |
end | |
end | |
def -(ob) | |
case ob | |
when Root | |
self + (-ob) | |
else | |
super(ob) | |
end | |
end | |
def ==(ob) | |
case ob | |
when Root | |
ob == self | |
else | |
super(ob) | |
end | |
end | |
def <=>(ob) | |
case ob | |
when Root | |
-1 * (ob <=> self) | |
else | |
super(ob) | |
end | |
end | |
def <(ob) | |
case ob | |
when Root | |
ob > self | |
else | |
super(ob) | |
end | |
end | |
def >(ob) | |
ob < self | |
end | |
def >=(ob) | |
case ob | |
when Root | |
ob <= self | |
else | |
super(ob) | |
end | |
end | |
def <=(ob) | |
ob >= self | |
end | |
[Integer, Rational, Float].each do |klass| | |
klass.send(:prepend, ExRoot) | |
end | |
end | |
class Root | |
def initialize(*args) | |
case args.size | |
when 2 | |
a = args[0] * Root.new(args[1]) | |
@coefficient = a.coefficient | |
@content = a.content | |
when 1 | |
num = args[0] | |
case num | |
when Integer | |
@coefficient = 1 | |
@content = num | |
convert | |
when Rational | |
r_to_root(num) | |
when Float | |
r_to_root(num.rationalize) | |
else | |
error(num) | |
end | |
else | |
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 1 or 2)" | |
end | |
end | |
attr_accessor :coefficient, :content | |
protected :coefficient=, :content= | |
def *(ob) | |
case ob | |
when Root | |
a = Root.new(1) | |
a.coefficient = @coefficient * ob.coefficient | |
a.content = @content * ob.content | |
a.convert | |
a.int_check | |
when Integer, Rational | |
self * Root.new(ob * ob) | |
when Float | |
self * ob.rationalize | |
else | |
error(ob) | |
end | |
end | |
def /(ob) | |
case ob | |
when Integer, Rational | |
self * Rational(1, ob) | |
when Float | |
self / ob.rationalize | |
when Root | |
self * Root.new(Rational(1, ob.content)) * Rational(1, ob.coefficient) | |
else | |
error(ob) | |
end | |
end | |
def **(ob) | |
case ob | |
when Integer | |
a = copy | |
a.coefficient **= ob | |
a.coefficient *= @content ** (ob / 2) | |
a.content **= ob % 2 | |
a.int_check | |
when Rational, Float | |
to_f ** ob | |
else | |
error(ob) | |
end | |
end | |
def +(ob) | |
case ob | |
when Root | |
return ob if @coefficient.zero? | |
if @content == ob.content | |
a = copy | |
a.coefficient += ob.coefficient | |
return a.int_check | |
end | |
when Integer, Rational | |
(@content == 1) ? (return @coefficient + ob) : error(self) | |
when Float | |
return to_f + ob | |
end | |
error(ob) | |
end | |
def -(ob) | |
self + (-ob) | |
end | |
def -@ | |
a = copy | |
a.coefficient = -a.coefficient | |
a | |
end | |
def +@ | |
int_check | |
end | |
def int_check | |
return 0 if @coefficient.zero? | |
(@content == 1) ? @coefficient : self | |
end | |
def inspect | |
if @coefficient == 1 | |
"Root(#{@content})" | |
else | |
"(#{@coefficient})Root(#{@content})" | |
end | |
end | |
def to_s | |
inspect | |
end | |
def to_f | |
@coefficient * Math.sqrt(@content) | |
end | |
def to_i | |
to_f.to_i | |
end | |
def <(ob) | |
to_f < ob.to_f | |
end | |
def >(ob) | |
to_f > ob.to_f | |
end | |
def ==(ob) | |
case ob | |
when Root | |
@content == ob.content and @coefficient == ob.coefficient | |
else | |
to_f == ob.to_f | |
end | |
end | |
def >=(ob) | |
self > ob or self == ob | |
end | |
def <=(ob) | |
self < ob or self == ob | |
end | |
def <=>(ob) | |
if self == ob | |
0 | |
elsif self > ob | |
1 | |
else | |
-1 | |
end | |
end | |
def to_root | |
self | |
end | |
protected | |
def convert | |
if @content.zero? | |
@content = 1 | |
@coefficient = 0 | |
else | |
c = 1 | |
Prime.prime_division(@content).each do |a| | |
@coefficient *= a[0] ** (a[1] / 2) | |
c *= a[0] ** (a[1] % 2) | |
end | |
@content = c | |
end | |
end | |
def copy | |
a = Root.new(1) | |
a.coefficient = @coefficient | |
a.content = @content | |
a | |
end | |
private | |
def r_to_root(num) | |
deno = num.denominator | |
@coefficient = Rational(1, deno) | |
@content = num.numerator * deno | |
convert | |
end | |
def error(num) | |
raise TypeError, "#{num} (Class #{num.class}) can not be used at this place." | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment