Skip to content

Commit 6983722

Browse files
authored
rational.c: convert a numerator to rational before calling fdiv in Kernel.Rational() (#3702)
This makes `Rational(BigDecimal(1), 60) == Rational(1, 60)`. [Bug #16518]
1 parent 52c630d commit 6983722

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

rational.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2673,8 +2673,16 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
26732673
}
26742674
}
26752675
if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2676-
(!f_integer_p(a1) || !f_integer_p(a2)))
2676+
(!f_integer_p(a1) || !f_integer_p(a2))) {
2677+
VALUE tmp = rb_protect(to_rational, a1, &state);
2678+
if (!state) {
2679+
a1 = tmp;
2680+
}
2681+
else {
2682+
rb_set_errinfo(Qnil);
2683+
}
26772684
return f_div(a1, a2);
2685+
}
26782686
}
26792687

26802688
a1 = nurat_int_value(a1);

test/ruby/test_rational.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,14 @@ def o.to_r; raise; end
165165
if (1.0/0).infinite?
166166
assert_raise(FloatDomainError){Rational(1.0/0)}
167167
end
168+
169+
bug16518 = "[ruby-core:96942] [Bug #16518]"
170+
cls = Class.new(Numeric) do
171+
def /(y); 42; end
172+
def to_r; 1r; end
173+
def to_int; 1; end
174+
end
175+
assert_equal(1/2r, Rational(cls.new, 2))
168176
end
169177

170178
def test_attr

0 commit comments

Comments
 (0)