summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-07-07 07:37:55 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-07-07 07:37:55 +0000
commit9bb27fa318928464f5ab66649a75bbd034307baa (patch)
tree0ab24af61bc3fe18bd6fccc658fd2350a03c5984
parent415059abf14c63979621be79512713772f9e9970 (diff)
numeric.c: round nearly middle value
* numeric.c (flo_round): [EXPERIMENTAL] adjust the case that the receiver is close to the exact but unrepresentable middle value of two values in the given precision. http://d.hatena.ne.jp/hnw/20160702 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55604 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog7
-rw-r--r--numeric.c11
-rw-r--r--test/ruby/test_float.rb5
3 files changed, 21 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 5dbd688284..59bff9542a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Thu Jul 7 16:37:53 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (flo_round): [EXPERIMENTAL] adjust the case that the
+ receiver is close to the exact but unrepresentable middle value
+ of two values in the given precision.
+ http://d.hatena.ne.jp/hnw/20160702
+
Thu Jul 7 16:31:07 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
* io.c (rb_io_s_foreach, rb_io_s_readlines): convert arguments
diff --git a/numeric.c b/numeric.c
index c92b7b430b..b806ceca3c 100644
--- a/numeric.c
+++ b/numeric.c
@@ -1990,7 +1990,7 @@ rb_int_truncate(VALUE num, int ndigits)
static VALUE
flo_round(int argc, VALUE *argv, VALUE num)
{
- double number, f;
+ double number, f, x;
int ndigits = 0;
if (rb_check_arity(argc, 0, 1)) {
@@ -2005,7 +2005,14 @@ flo_round(int argc, VALUE *argv, VALUE num)
}
if (float_invariant_round(number, ndigits, &num)) return num;
f = pow(10, ndigits);
- return DBL2NUM(round(number * f) / f);
+ x = round(number * f);
+ if (x > 0) {
+ if ((x + 0.5) / f <= number) x += 1;
+ }
+ else {
+ if ((x - 0.5) / f >= number) x -= 1;
+ }
+ return DBL2NUM(x / f);
}
static int
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index 06b1d85242..2684cd8eab 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -447,6 +447,11 @@ class TestFloat < Test::Unit::TestCase
assert_raise(TypeError) {1.0.round(nil)}
def (prec = Object.new).to_int; 2; end
assert_equal(1.0, 0.998.round(prec))
+
+ assert_equal(+5.02, +5.015.round(2))
+ assert_equal(-5.02, -5.015.round(2))
+ assert_equal(+1.26, +1.255.round(2))
+ assert_equal(-1.26, -1.255.round(2))
end
def test_floor_with_precision