Skip to content

Instantly share code, notes, and snippets.

@obelisk68
Last active November 16, 2018 15:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save obelisk68/8744c8aa60f10072a4a7b440f4104e34 to your computer and use it in GitHub Desktop.
Save obelisk68/8744c8aa60f10072a4a7b440f4104e34 to your computer and use it in GitHub Desktop.
平方根の計算
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