From: Shin-ichiro HARA Date: 2006-04-30T22:22:20+09:00 Subject: [ruby-dev:28609] Re: Float#div and Float#divmod [AGAIN] 原です。 >まつもと ゆきひろです >|どちらもバグ扱いで 1.8.4 で直してもいいと思います。 > >というわけで、原さんがコミットして下さるとうれしいなあ。 コミット権の件は後にして、パッチを流します。ほとんどドキュ メントの差分ですが。 ところで、現在の 1.8.4 安定版スナップショットは、そのまま で make test でエラーが3つ出ます。原因は util.c の strtod のバグだと思います。1.9.0 の util.c の strtod にごっそり置 き換えると直ります。 更に、test/ruby/test_float.rb に次のコードを足すといいかも: def test_divmod assert_equal([2, 3.5], 11.5.divmod(4)) assert_equal([-3, -0.5], 11.5.divmod(-4)) assert_equal([-3, 0.5], (-11.5).divmod(4)) assert_equal([2, -3.5], (-11.5).divmod(-4)) end def test_div assert_equal(2, 11.5.div(4)) assert_equal(-3, 11.5.div(-4)) assert_equal(-3, (-11.5).div(4)) assert_equal(2, (-11.5).div(-4)) end def test_modulo assert_equal(3.5, 11.5.modulo(4)) assert_equal(-0.5, 11.5.modulo(-4)) assert_equal(0.5, (-11.5).modulo(4)) assert_equal(-3.5, (-11.5).modulo(-4)) end def test_remainder assert_equal(3.5, 11.5.remainder(4)) assert_equal(3.5, 11.5.remainder(-4)) assert_equal(-3.5, (-11.5).remainder(4)) assert_equal(-3.5, (-11.5).remainder(-4)) end 以下パッチです。 --- numeric.c.orig 2006-02-05 21:09:31.000000000 +0900 +++ numeric.c 2006-04-30 22:00:43.265625000 +0900 @@ -256,6 +256,8 @@ } +static VALUE num_floor(VALUE num); + /* * call-seq: * num.div(numeric) => integer @@ -269,7 +271,7 @@ num_div(x, y) VALUE x, y; { - return rb_Integer(rb_funcall(x, '/', 1, y)); + return num_floor(rb_funcall(x, '/', 1, y)); } @@ -297,21 +299,21 @@ * ------+-----+---------------+---------+-------------+--------------- * -13 | -4 | 3, -1 | 3 | -1 | -1 * ------+-----+---------------+---------+-------------+--------------- - * 11.5 | 4 | 2.0, 3.5 | 2.875 | 3.5 | 3.5 + * 11.5 | 4 | 2, 3.5 | 2.875 | 3.5 | 3.5 * ------+-----+---------------+---------+-------------+--------------- - * 11.5 | -4 | -3.0, -0.5 | -2.875 | -0.5 | 3.5 + * 11.5 | -4 | -3, -0.5 | -2.875 | -0.5 | 3.5 * ------+-----+---------------+---------+-------------+--------------- - * -11.5 | 4 | -3.0 0.5 | -2.875 | 0.5 | -3.5 + * -11.5 | 4 | -3, 0.5 | -2.875 | 0.5 | -3.5 * ------+-----+---------------+---------+-------------+--------------- - * -11.5 | -4 | 2.0 -3.5 | 2.875 | -3.5 | -3.5 + * -11.5 | -4 | 2 -3.5 | 2.875 | -3.5 | -3.5 * * * Examples * 11.divmod(3) #=> [3, 2] * 11.divmod(-3) #=> [-4, -1] - * 11.divmod(3.5) #=> [3.0, 0.5] - * (-11).divmod(3.5) #=> [-4.0, 3.0] - * (11.5).divmod(3.5) #=> [3.0, 1.0] + * 11.divmod(3.5) #=> [3, 0.5] + * (-11).divmod(3.5) #=> [-4, 3.0] + * (11.5).divmod(3.5) #=> [3, 1.0] */ static VALUE @@ -715,7 +717,7 @@ flo_divmod(x, y) VALUE x, y; { - double fy, div, mod; + double fy, div, mod, val; volatile VALUE a, b; switch (TYPE(y)) { @@ -732,7 +734,13 @@ return rb_num_coerce_bin(x, y); } flodivmod(RFLOAT(x)->value, fy, &div, &mod); - a = rb_float_new(div); + if (FIXABLE(div)) { + val = div; + a = LONG2FIX(val); + } + else { + a = rb_dbl2big(div); + } b = rb_float_new(mod); return rb_assoc_new(a, b); }