From: nobu.nokada@... Date: 2003-04-18T01:14:07+09:00 Subject: Re: Roundoff problem with Float and Marshal Hi, At Fri, 18 Apr 2003 00:22:02 +0900, Yukihiro Matsumoto wrote: > |Everything is working fine for 3.95601527633861 > |PROBLEM: a is 3.7517675036461267e+17, b is 3.7517675036461261e+17, > |and ma is "\004\010f\e3.7517675036461267e+17" > > This is caused by bad implementation of strtod that Ruby 1.8 uses (in > util.c). I will seek for the better one. Hmmm, it seems so. $ ruby -e 'p 3.7517675036461267e+17' 3.7517675036461261e+17 Index: util.c =================================================================== RCS file: /pub/cvs/ruby/src/ruby/util.c,v retrieving revision 1.32 diff -u -2 -p -w -r1.32 util.c --- util.c 16 Jan 2003 07:34:03 -0000 1.32 +++ util.c 17 Apr 2003 16:10:57 -0000 @@ -16,4 +16,5 @@ #include #include +#include #ifdef _WIN32 @@ -807,5 +808,4 @@ ruby_strtod(string, endPtr) fraction = 0.0; p = string; - goto done; } else { @@ -831,6 +831,4 @@ ruby_strtod(string, endPtr) frac2 = 10*frac2 + (c - '0'); } - fraction = (1.0e9 * frac1) + frac2; - } /* @@ -880,5 +878,9 @@ ruby_strtod(string, endPtr) exp = maxExponent; errno = ERANGE; + fraction = HUGE; } + else { + fracExp = exp; + exp += 9; dblExp = 1.0; for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { @@ -888,11 +890,25 @@ ruby_strtod(string, endPtr) } if (expSign) { - fraction /= dblExp; + fraction = frac1 / dblExp; } else { - fraction *= dblExp; + fraction = frac1 * dblExp; + } + exp = fracExp; + dblExp = 1.0; + for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { + if (exp & 01) { + dblExp *= *d; + } + } + if (expSign) { + fraction += frac2 / dblExp; + } + else { + fraction += frac2 * dblExp; + } + } } -done: if (endPtr != NULL) { *endPtr = (char *) p; -- Nobu Nakada