Project

General

Profile

Actions

Bug #14637

closed

Rational#to_f returns a wrong result when denominator is big

Added by mame (Yusuke Endoh) about 6 years ago. Updated almost 6 years ago.

Status:
Closed
Target version:
-
[ruby-core:86330]

Description

For example, Rational(1, 10**23).to_f returns a wrong result:

$ ruby -e 'p Rational(1, 10**23).to_f'
1.0000000000000001e-23

It should be 1.0e-23. A Float value 1.0000000000000001e-23 ranges from 0.1000000000000000033903094915171e-22 to 0.1000000000000000180839888707781e-22. This range does not include 1 / 10**23.

This is because Rational#to_f does: (1) translate numerator and denominator to double values, and (2) divide them. When denominator is big, it cannot translate denominator to double accurately, which causes the above bug.

We can avoid this inaccurance by translating numerator and denominator to small bignums, instead of double values.

diff --git a/bignum.c b/bignum.c
index b4c7560034..fd5f385cac 100644
--- a/bignum.c
+++ b/bignum.c
@@ -6178,9 +6178,7 @@ rb_big_fdiv_double(VALUE x, VALUE y)
 	    return big_fdiv_int(x, rb_int2big(FIX2LONG(y)));
     }
     else if (RB_BIGNUM_TYPE_P(y)) {
-	dy = rb_big2dbl(y);
-	if (isinf(dx) || isinf(dy))
-	    return big_fdiv_int(x, y);
+	return big_fdiv_int(x, y);
     }
     else if (RB_FLOAT_TYPE_P(y)) {
 	dy = RFLOAT_VALUE(y);

Updated by mame (Yusuke Endoh) about 6 years ago

  • Status changed from Open to Assigned
  • Assignee set to mame (Yusuke Endoh)

I'll commit in a few days unless anyone has objection.

Actions #2

Updated by mame (Yusuke Endoh) almost 6 years ago

  • Status changed from Assigned to Closed

Applied in changeset trunk|r63093.


bignum.c: Bignum#fdiv avoids double division when divisor is bignum

Rational(int, bignum).to_f sometimes returned a wrong result because
Bignum#div casted its divisor to double. [Bug #14637] [ruby-core:86330]

Actions

Also available in: Atom PDF

Like0
Like0Like0