Last active
November 16, 2018 15:57
-
-
Save obelisk68/8744c8aa60f10072a4a7b440f4104e34 to your computer and use it in GitHub Desktop.
平方根の計算
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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