山本です。 レスがつかなかったので、意図された動作なのかもしれませんが・・・ HEAD の実装だと、 E:\ruby-cvs\ruby>miniruby -e "p 0.0" 0.0e+00 E:\ruby-cvs\ruby>miniruby -e "p 0.00000000001" 9.999999999999999e-12 となります。 下のパッチだと、 E:\ruby-cvs\ruby>miniruby -e "p 0.0" 0.0 E:\ruby-cvs\ruby>miniruby -e "p 0.00000000001" 1.0e-11 となります。 DBL_DIG は定数式とは限らない(http://www-ccs.ucsd.edu/c/float.html)らしいので やむなく ALLOCA_N を使いました。もっといい方法をご存知の方、教えてください。 Index: numeric.c =================================================================== RCS file: /ruby/ruby/numeric.c,v retrieving revision 1.108 diff -u -w -b -p -r1.108 numeric.c --- numeric.c 10 May 2004 08:23:13 -0000 1.108 +++ numeric.c 14 May 2004 02:13:38 -0000 @@ -3,7 +3,7 @@ numeric.c - $Author: matz $ - $Date: 2004/05/10 08:23:13 $ + $Date: 2004/05/07 08:44:15 $ created at: Fri Aug 13 18:33:09 JST 1993 Copyright (C) 1993-2003 Yukihiro Matsumoto @@ -489,10 +489,9 @@ static VALUE flo_to_s(flt) VALUE flt; { - char buf[32]; - char *fmt = "%.15f"; + char fmt[sizeof(int)*3+10], *buf; double value = RFLOAT(flt)->value; - double avalue, d1, d2; + int exp; char *p, *e; if (isinf(value)) @@ -500,13 +499,26 @@ flo_to_s(flt) else if(isnan(value)) return rb_str_new2("NaN"); - avalue = fabs(value); - if (avalue < 1.0e-7 || avalue >= 1.0e15) { - fmt = "%.15e"; - } + buf = ALLOCA_N(char, DBL_DIG+sizeof(int)*3+20); + sprintf(fmt, "%%.%de", DBL_DIG - 1); sprintf(buf, fmt, value); - if (!(e = strchr(buf, 'e'))) { - e = buf + strlen(buf); + e = strchr(buf, 'e'); + exp = atoi(e+1); + if (-7 <= exp && exp < DBL_DIG - 1) { + char *d = strchr(buf, '.'); + if (exp > 0) { + memmove(d, d+1, exp); + d[exp] = '.'; + } + if (exp < 0) { /* needs room in `buf' for shifting */ + int n = -exp; + d[0] = d[-1]; + memmove(d+n, d, strlen(d)+1); + e += n; + memset(buf, '0', n+1); + buf[1] = '.'; + } + *e = '\0'; } p = e; while (*--p=='0')