1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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
This commit is contained in:
nobu 2016-07-07 07:37:55 +00:00
parent 415059abf1
commit 9bb27fa318
3 changed files with 21 additions and 2 deletions

View file

@ -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> 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 * io.c (rb_io_s_foreach, rb_io_s_readlines): convert arguments

View file

@ -1990,7 +1990,7 @@ rb_int_truncate(VALUE num, int ndigits)
static VALUE static VALUE
flo_round(int argc, VALUE *argv, VALUE num) flo_round(int argc, VALUE *argv, VALUE num)
{ {
double number, f; double number, f, x;
int ndigits = 0; int ndigits = 0;
if (rb_check_arity(argc, 0, 1)) { 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; if (float_invariant_round(number, ndigits, &num)) return num;
f = pow(10, ndigits); 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 static int

View file

@ -447,6 +447,11 @@ class TestFloat < Test::Unit::TestCase
assert_raise(TypeError) {1.0.round(nil)} assert_raise(TypeError) {1.0.round(nil)}
def (prec = Object.new).to_int; 2; end def (prec = Object.new).to_int; 2; end
assert_equal(1.0, 0.998.round(prec)) 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 end
def test_floor_with_precision def test_floor_with_precision