ruby-changes:43531
From: nobu <ko1@a...>
Date: Thu, 7 Jul 2016 16:38:00 +0900 (JST)
Subject: [ruby-changes:43531] nobu:r55604 (trunk): numeric.c: round nearly middle value
nobu 2016-07-07 16:37:55 +0900 (Thu, 07 Jul 2016) New Revision: 55604 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=55604 Log: 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 Modified files: trunk/ChangeLog trunk/numeric.c trunk/test/ruby/test_float.rb Index: numeric.c =================================================================== --- numeric.c (revision 55603) +++ numeric.c (revision 55604) @@ -1990,7 +1990,7 @@ rb_int_truncate(VALUE num, int ndigits) https://github.com/ruby/ruby/blob/trunk/numeric.c#L1990 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 n https://github.com/ruby/ruby/blob/trunk/numeric.c#L2005 } 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 Index: ChangeLog =================================================================== --- ChangeLog (revision 55603) +++ ChangeLog (revision 55604) @@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Jul 7 16:37:53 2016 Nobuyoshi Nakada <nobu@r...> + + * 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@r...> * io.c (rb_io_s_foreach, rb_io_s_readlines): convert arguments Index: test/ruby/test_float.rb =================================================================== --- test/ruby/test_float.rb (revision 55603) +++ test/ruby/test_float.rb (revision 55604) @@ -447,6 +447,11 @@ class TestFloat < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_float.rb#L447 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 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/