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]
This commit is contained in:
Kenta Murata 2020-10-26 18:43:30 +09:00 коммит произвёл GitHub
Родитель 52c630da00
Коммит 69837229d7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 17 добавлений и 1 удалений

Просмотреть файл

@ -2673,8 +2673,16 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
} }
} }
if ((k_numeric_p(a1) && k_numeric_p(a2)) && if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
(!f_integer_p(a1) || !f_integer_p(a2))) (!f_integer_p(a1) || !f_integer_p(a2))) {
VALUE tmp = rb_protect(to_rational, a1, &state);
if (!state) {
a1 = tmp;
}
else {
rb_set_errinfo(Qnil);
}
return f_div(a1, a2); return f_div(a1, a2);
}
} }
a1 = nurat_int_value(a1); a1 = nurat_int_value(a1);

Просмотреть файл

@ -165,6 +165,14 @@ class Rational_Test < Test::Unit::TestCase
if (1.0/0).infinite? if (1.0/0).infinite?
assert_raise(FloatDomainError){Rational(1.0/0)} assert_raise(FloatDomainError){Rational(1.0/0)}
end end
bug16518 = "[ruby-core:96942] [Bug #16518]"
cls = Class.new(Numeric) do
def /(y); 42; end
def to_r; 1r; end
def to_int; 1; end
end
assert_equal(1/2r, Rational(cls.new, 2))
end end
def test_attr def test_attr