From 11ba3e2331952f17dd5391b32db0964b4c29ddb9 Mon Sep 17 00:00:00 2001 From: matz Date: Thu, 11 May 2006 10:59:12 +0000 Subject: * util.c (ruby_strtod): differ addition to minimize error. [ruby-dev:28619] git-svn-id: http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8@10146 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ util.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index b2f0c13c9..1745b3ab1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Thu May 11 19:57:00 2006 Yukihiro Matsumoto + + * util.c (ruby_strtod): differ addition to minimize error. + [ruby-dev:28619] + Thu May 11 18:10:43 2006 Yukihiro Matsumoto * util.c (ruby_strtod): should not raise ERANGE when the input diff --git a/util.c b/util.c index 1b6094850..9424fa58e 100644 --- a/util.c +++ b/util.c @@ -811,12 +811,26 @@ ruby_strtod(string, endPtr) p = string; } else { - for (; mantSize > 0; mantSize--) { - c = *p++; + double frac1, frac2; + frac1 = 0; + for ( ; mantSize > 9; mantSize -= 1) { + c = *p; + p += 1; if (c == '.') { - c = *p++; + c = *p; + p += 1; } - fraction = 10*fraction + (c - '0'); + frac1 = 10*frac1 + (c - '0'); + } + frac2 = 0; + for (; mantSize > 0; mantSize -= 1) { + c = *p; + p += 1; + if (c == '.') { + c = *p; + p += 1; + } + frac2 = 10*frac2 + (c - '0'); } /* @@ -868,6 +882,8 @@ ruby_strtod(string, endPtr) errno = ERANGE; return 0.0 * (sign ? -1.0 : 1.0); } + fracExp = exp; + exp += 9; if (exp < 0) { expSign = Qtrue; exp = -exp; @@ -876,23 +892,45 @@ ruby_strtod(string, endPtr) expSign = Qfalse; } dblExp = 10.0; - while (exp) - { - if (exp & 1) { - if (expSign) - fraction /= dblExp; - else - fraction *= dblExp; + while (exp) { + if (exp & 01) { + if (expSign) { + frac1 /= dblExp; + } + else { + frac1 *= dblExp; + } } exp >>= 1; dblExp *= dblExp; } + exp = fracExp; + if (exp < 0) { + expSign = Qtrue; + exp = -exp; + } + else { + expSign = Qfalse; + } + dblExp = 10.0; + while (exp) { + if (exp & 01) { + if (expSign) { + frac2 /= dblExp; + } + else { + frac2 *= dblExp; + } + } + exp >>= 1; + dblExp *= dblExp; + } + fraction = frac1 + frac2; } if (endPtr != NULL) { *endPtr = (char *)p; } - if (sign) { return -fraction; } -- cgit