Commit f5fb1307 authored by KOBAYASHI Shuji's avatar KOBAYASHI Shuji

Fix `Rational#==`

parent 9b604abc
...@@ -3,7 +3,6 @@ MRuby::Gem::Specification.new('mruby-rational') do |spec| ...@@ -3,7 +3,6 @@ MRuby::Gem::Specification.new('mruby-rational') do |spec|
spec.author = 'mruby developers' spec.author = 'mruby developers'
spec.summary = 'Rational class' spec.summary = 'Rational class'
spec.add_dependency 'mruby-metaprog', core: 'mruby-metaprog'
spec.add_dependency 'mruby-object-ext', core: 'mruby-object-ext' spec.add_dependency 'mruby-object-ext', core: 'mruby-object-ext'
spec.add_dependency 'mruby-numeric-ext', core: 'mruby-numeric-ext' spec.add_dependency 'mruby-numeric-ext', core: 'mruby-numeric-ext'
end end
class Rational < Numeric class Rational < Numeric
# Override #<, #<=, #>, #>= in Numeric
prepend Comparable
def initialize(numerator = 0, denominator = 1) def initialize(numerator = 0, denominator = 1)
@numerator = numerator @numerator = numerator
@denominator = denominator @denominator = denominator
...@@ -66,6 +69,24 @@ class Rational < Numeric ...@@ -66,6 +69,24 @@ class Rational < Numeric
end end
end end
def <=>(rhs)
case rhs
when Fixnum
return @numerator <=> rhs if @denominator == 1
rhs = Rational(rhs)
when Float
return to_f <=> rhs
end
case rhs
when Rational
(@numerator * rhs.denominator - @denominator * rhs.numerator) <=> 0
when Numeric
return rhs <=> self
else
nil
end
end
def negative? def negative?
numerator.negative? numerator.negative?
end end
...@@ -86,15 +107,15 @@ def Rational(numerator = 0, denominator = 1) ...@@ -86,15 +107,15 @@ def Rational(numerator = 0, denominator = 1)
end end
[Fixnum, Float].each do |cls| [Fixnum, Float].each do |cls|
[:+, :-, :*, :/, :==].each do |op| [:+, :-, :*, :/, :<=>, :==, :<, :<=, :>, :>=].each do |op|
cls.instance_exec do cls.instance_exec do
original_operator_name = "__original_operator_#{op}_rational" original_operator_name = "__original_operator_#{op}_rational"
alias_method original_operator_name, op alias_method original_operator_name, op
define_method op do |rhs| define_method op do |rhs|
if rhs.is_a? Rational if rhs.is_a? Rational
Rational(self).send(op, rhs) Rational(self).__send__(op, rhs)
else else
send(original_operator_name, rhs) __send__(original_operator_name, rhs)
end end
end end
end end
......
...@@ -3,6 +3,16 @@ def assert_rational(real, exp) ...@@ -3,6 +3,16 @@ def assert_rational(real, exp)
assert_float real.denominator, exp.denominator assert_float real.denominator, exp.denominator
end end
def assert_equal_rational(exp, r1, r2)
if exp
assert_operator(r1, :==, r2)
assert_not_operator(r1, :!=, r2)
else
assert_not_operator(r1, :==, r2)
assert_operator(r1, :!=, r2)
end
end
assert 'Rational' do assert 'Rational' do
r = 5r r = 5r
assert_equal Rational, r.class assert_equal Rational, r.class
...@@ -55,3 +65,38 @@ assert 'Rational#/' do ...@@ -55,3 +65,38 @@ assert 'Rational#/' do
assert_rational Rational(9, 8) / 4, Rational(9, 32) assert_rational Rational(9, 8) / 4, Rational(9, 32)
assert_float Rational(20, 9) / 9.8, 0.22675736961451246 assert_float Rational(20, 9) / 9.8, 0.22675736961451246
end end
assert 'Rational#==, Rational#!=' do
assert_equal_rational(true, Rational(1,1), Rational(1))
assert_equal_rational(true, Rational(-1,1), -1r)
assert_equal_rational(true, Rational(13,4), 3.25)
assert_equal_rational(true, Rational(13,3.25), Rational(4,1))
assert_equal_rational(true, Rational(-3,-4), Rational(3,4))
assert_equal_rational(true, Rational(-4,5), Rational(4,-5))
assert_equal_rational(true, Rational(4,2), 2)
assert_equal_rational(true, Rational(-4,2), -2)
assert_equal_rational(true, Rational(4,-2), -2)
assert_equal_rational(true, Rational(4,2), 2.0)
assert_equal_rational(true, Rational(-4,2), -2.0)
assert_equal_rational(true, Rational(4,-2), -2.0)
assert_equal_rational(true, Rational(8,6), Rational(4,3))
assert_equal_rational(false, Rational(13,4), 3)
assert_equal_rational(false, Rational(13,4), 3.3)
assert_equal_rational(false, Rational(2,1), 1r)
assert_equal_rational(false, Rational(1), nil)
assert_equal_rational(false, Rational(1), '')
end
assert 'Fixnum#==(Rational), Fixnum#!=(Rational)' do
assert_equal_rational(true, 2, Rational(4,2))
assert_equal_rational(true, -2, Rational(-4,2))
assert_equal_rational(true, -2, Rational(4,-2))
assert_equal_rational(false, 3, Rational(13,4))
end
assert 'Float#==(Rational), Float#!=(Rational)' do
assert_equal_rational(true, 2.0, Rational(4,2))
assert_equal_rational(true, -2.0, Rational(-4,2))
assert_equal_rational(true, -2.0, Rational(4,-2))
assert_equal_rational(false, 3.3, Rational(13,4))
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment