From: Tadayoshi Funaba Date: 2006-04-09T14:59:54+09:00 Subject: [ruby-dev:28530] Re: Rational ふなばです。 rational/rationalize の話をしたので、原さんの rational 1.00 の Rational(aFloat) と比べてみました。 原さんの Rational 1.00 ではこうなりますが、 Rational(0.3) => 2702159776422297/9007199254740992 いくつかの Common Lisp や Haskell 処理系などで、浮動小数点数の書式が同 じ場合、rational や toRational の結果はちゃんと一致しているようです。 というか、そうじゃないものはみつけられませんでした。 (rational 0.3f0) => 5033165/16777216 (rational 0.3d0) => 5404319552844595/18014398509481984 toRational (0.3::Float) => 5033165 % 16777216 toRational (0.3::Double) => 5404319552844595 % 18014398509481984 (inexact->exact 0.3) => 5404319552844595/18014398509481984 0.3 asFraction => (5404319552844595/18014398509481984) など。 とりあえず、原さんの Rational 1.00 も rb_rat_flo_to_rat() をつぎのよう にすると、同様になりそうです。 static VALUE rb_rat_flo_to_rat(klass, x) double x; { double f; int e; f = frexp(x, &e); #if 1 /* dbl */ f = ldexp(f, DBL_MANT_DIG); e -= DBL_MANT_DIG; #else /* flt */ f = (float)ldexp(f, FLT_MANT_DIG); e -= FLT_MANT_DIG; #endif return RT_S_NEW2(klass, RT_MUL(rb_dbl2big(f), RT_POW(rb_int2big(2), INT2FIX(e))), INT2FIX(1)); } # コード上の数字 2 は、FLT_RADIX にすべきかも。 CL の仕様書によれば「浮動小数点数は (数学的には) s*f*b^(e-p) の形式の 有理数である」らしいので。これに従えば、問題なく中身が取り出せているな らば、結果も定まるように思います。 今のところ、どうすべきか、ということはないのですが、なぜ違うのかはちょっ と疑問です。 rationalize のほうは、モノにもよりますが、rational の10倍前後遅いみた いですね。なんか難しいことをしているのでしょうか。これを to_r にするの は少し厳しいのかも。とりあえず、僕がみたかぎりでは、rational のほうが 普通っぽいようです。