From 694059769211a571169e9e7b7707668981631548 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 17 Apr 2003 16:49:23 +0000 Subject: [PATCH] * util.c (ruby_strtod): improved conversion accuracy. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3692 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 4 ++ util.c | 137 +++++++++++++++++++++++++++++++----------------------- 2 files changed, 84 insertions(+), 57 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4fb0713789..7c3e425922 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Fri Apr 18 01:49:18 2003 Nobuyoshi Nakada + + * util.c (ruby_strtod): improved conversion accuracy. + Thu Apr 17 14:39:23 2003 NAKAMURA Usaku * ext/dbm/dbm.c (each_pair): add prototype to avoid VC++ warnings. diff --git a/util.c b/util.c index 965192e44d..b0cf8256bd 100644 --- a/util.c +++ b/util.c @@ -246,10 +246,10 @@ valid_filename(char *s) /* // It doesn't exist, so see if we can open it. */ - + if ((fd = _open(s, O_CREAT, 0666)) >= 0) { _close(fd); - _unlink (s); /* don't leave it laying around */ + _unlink(s); /* don't leave it laying around */ return 1; } return 0; @@ -806,7 +806,6 @@ ruby_strtod(string, endPtr) if (mantSize == 0) { fraction = 0.0; p = string; - goto done; } else { int frac1, frac2; @@ -830,70 +829,94 @@ ruby_strtod(string, endPtr) } frac2 = 10*frac2 + (c - '0'); } - fraction = (1.0e9 * frac1) + frac2; - } - /* - * Skim off the exponent. - */ + /* + * Skim off the exponent. + */ - p = pExp; - if ((*p == 'E') || (*p == 'e')) { - p += 1; - if (*p == '-') { - expSign = TRUE; + p = pExp; + if ((*p == 'E') || (*p == 'e')) { p += 1; - } - else { - if (*p == '+') { + if (*p == '-') { + expSign = TRUE; p += 1; } + else { + if (*p == '+') { + p += 1; + } + expSign = FALSE; + } + while (ISDIGIT(*p)) { + exp = exp * 10 + (*p - '0'); + p += 1; + } + } + if (expSign) { + exp = fracExp - exp; + } + else { + exp = fracExp + exp; + } + + /* + * Generate a floating-point number that represents the exponent. + * Do this by processing the exponent one bit at a time to combine + * many powers of 2 of 10. Then combine the exponent with the + * fraction. + */ + + if (exp > maxExponent) { + exp = maxExponent; + errno = ERANGE; + } + else if (exp < -maxExponent) { + exp = -maxExponent; + errno = ERANGE; + } + fracExp = exp; + exp += 9; + if (exp < 0) { + expSign = TRUE; + exp = -exp; + } + else { expSign = FALSE; } - while (ISDIGIT(*p)) { - exp = exp * 10 + (*p - '0'); - p += 1; + dblExp = 1.0; + for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { + if (exp & 01) { + dblExp *= *d; + } + } + if (expSign) { + fraction = frac1 / dblExp; + } + else { + fraction = frac1 * dblExp; + } + exp = fracExp; + if (exp < 0) { + expSign = TRUE; + exp = -exp; + } + else { + expSign = FALSE; + } + 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; } } - if (expSign) { - exp = fracExp - exp; - } - else { - exp = fracExp + exp; - } - /* - * Generate a floating-point number that represents the exponent. - * Do this by processing the exponent one bit at a time to combine - * many powers of 2 of 10. Then combine the exponent with the - * fraction. - */ - - if (exp < 0) { - expSign = TRUE; - exp = -exp; - } - else { - expSign = FALSE; - } - if (exp > maxExponent) { - exp = maxExponent; - errno = ERANGE; - } - dblExp = 1.0; - for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { - if (exp & 01) { - dblExp *= *d; - } - } - if (expSign) { - fraction /= dblExp; - } - else { - fraction *= dblExp; - } - -done: if (endPtr != NULL) { *endPtr = (char *) p; }