summaryrefslogtreecommitdiff
path: root/numeric.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2021-07-26 11:20:27 -0700
committerJeremy Evans <code@jeremyevans.net>2021-08-06 15:03:51 -0700
commitd16b68cb2204eeb5af8bd39149202b630374c67f (patch)
treed14b41ad62a2ef2a5b2fc40f3917ffebf83d2d80 /numeric.c
parent0d3520b063b304708699d3b7ea82b0a5b0279555 (diff)
Use Rational for Float#round with ndigits > 14
ndigits higher than 14 can result in values that are slightly too large due to floating point limitations. Converting to rational for the calculation and then back to float fixes these issues. Fixes [Bug #14635] Fixes [Bug #17183] Co-authored by: Yusuke Endoh <mame@ruby-lang.org>
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4682
Diffstat (limited to 'numeric.c')
-rw-r--r--numeric.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/numeric.c b/numeric.c
index 5f7c16218a..a1801f9654 100644
--- a/numeric.c
+++ b/numeric.c
@@ -2230,6 +2230,10 @@ flo_round(int argc, VALUE *argv, VALUE num)
frexp(number, &binexp);
if (float_round_overflow(ndigits, binexp)) return num;
if (float_round_underflow(ndigits, binexp)) return DBL2NUM(0);
+ if (ndigits > 14) {
+ /* In this case, pow(10, ndigits) may not be accurate. */
+ return rb_flo_round_by_rational(argc, argv, num);
+ }
f = pow(10, ndigits);
x = ROUND_CALL(mode, round, (number, f));
return DBL2NUM(x / f);