diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-05-11 10:59:12 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-05-11 10:59:12 +0000 |
commit | b0c7f088aabf933cca10585539b133d589c5412e (patch) | |
tree | e9a6c6ca6eca1863fc3f9a74819a4fec0df12665 /util.c | |
parent | 5f5405a0865b85dd4d73e52e2bd1dd9cfcb819bf (diff) |
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@10146 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 62 |
1 files changed, 50 insertions, 12 deletions
@@ -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; } |