summaryrefslogtreecommitdiff
path: root/numeric.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-03-22 23:07:36 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-03-22 23:07:36 +0000
commit9b66922d7f7a231724090de9a8037f4e944b1764 (patch)
tree4c3a619f3620aff83ff1db7496bd5fa995984bc1 /numeric.c
parent24055b89c8fdf7de36ae6d613d18a65ed446ce59 (diff)
* numeric.c (flo_round): fix inaccurate results.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31158 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'numeric.c')
-rw-r--r--numeric.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/numeric.c b/numeric.c
index 0f316fad93..34c378ba8f 100644
--- a/numeric.c
+++ b/numeric.c
@@ -97,6 +97,9 @@ round(double x)
}
#endif
+static VALUE fix_mul(VALUE x, VALUE y);
+static VALUE int_pow(long x, unsigned long y);
+
static ID id_coerce, id_to_i, id_eq;
VALUE rb_cNumeric;
@@ -1492,7 +1495,15 @@ flo_round(int argc, VALUE *argv, VALUE num)
if (ndigits < 0) number = 0;
}
else {
- if (ndigits < 0) number /= f;
+ if (ndigits < 0) {
+ if (fabs(number) < f) return INT2FIX(0);
+ if (!FIXABLE(number)) {
+ VALUE f10 = int_pow(10, -ndigits);
+ num = rb_big_idiv(rb_dbl2big(number), f10);
+ return FIXNUM_P(num) ? fix_mul(num, f10) : rb_big_mul(num, f10);
+ }
+ number /= f;
+ }
else number *= f;
number = round(number);
if (ndigits < 0) number *= f;