From: Nobuyoshi Nakada Date: 2007-06-24T14:59:25+09:00 Subject: [ruby-dev:31043] Re: 0**2 causes division by zero なかだです。 At Sat, 23 Jun 2007 23:57:11 +0900, Yusuke ENDOH wrote in [ruby-dev:31040]: > ruby 1.9 で 0**2 を評価すると SIGFPE で落ちます。 すいません。チェックを後回しにして忘れてました。 > こんな感じでしょうか。ついでに余計な最適化も入れてみましたが、 > 余計でしたらはずしてください。 yのチェックはfix_pow()でやってますから、不要だと思います。xもそっ ちでしたほうがいいかも。 ついでにint_round()を見ていたのですが、ndigits==LONG_MINのとき に時間がかかりすぎて返ってこなくなりますね。エラーにするか0を返 すようにしたほうがよさそうです。 > # そういえば 0**0 は 1 でいいんでしょうか。 まぁいいんじゃないでしょうか。 Index: numeric.c =================================================================== --- numeric.c (revision 12591) +++ numeric.c (working copy) @@ -2331,4 +2331,5 @@ fix_pow(VALUE x, VALUE y) if (b == 1) return x; a = FIX2LONG(x); + if (a == 0) return INT2FIX(0); if (b > 0) { return int_pow(a, b); @@ -2902,7 +2903,5 @@ int_round(int argc, VALUE* argv, VALUE n int ndigits; - if (argc == 0) return num; - if (FIXNUM_P(num)) return num_round(argc, argv, num); - + if (argc == 0) return 0; rb_scan_args(argc, argv, "1", &n); ndigits = NUM2INT(n); @@ -2910,6 +2909,20 @@ int_round(int argc, VALUE* argv, VALUE n return rb_Float(num); } + if (ndigits == 0) { + return num; + } ndigits = -ndigits; + if (ndigits < 0) { + rb_raise(rb_eArgError, "ndigits out of range"); + } f = int_pow(10, ndigits); + if (FIXNUM_P(num) && FIXNUM_P(f)) { + SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f); + int neg = x < 0; + if (neg) x = -x; + x = (x + y / 2) / y * y; + if (neg) x = -x; + return LONG2NUM(x); + } h = rb_funcall(f, '/', 1, INT2FIX(2)); r = rb_funcall(num, '%', 1, f); -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦