strtod.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:6k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * strtod.c --
  3.  *
  4.  * Source code for the "strtod" library procedure.
  5.  *
  6.  * Copyright (c) 1988-1993 The Regents of the University of California.
  7.  * Copyright (c) 1994 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * RCS: @(#) $Id: strtod.c,v 1.6 2002/02/25 14:26:12 dgp Exp $
  13.  */
  14. #include "tclInt.h"
  15. #include "tclPort.h"
  16. #include <ctype.h>
  17. #ifndef TRUE
  18. #define TRUE 1
  19. #define FALSE 0
  20. #endif
  21. #ifndef NULL
  22. #define NULL 0
  23. #endif
  24. static int maxExponent = 511; /* Largest possible base 10 exponent.  Any
  25.  * exponent larger than this will already
  26.  * produce underflow or overflow, so there's
  27.  * no need to worry about additional digits.
  28.  */
  29. static double powersOf10[] = { /* Table giving binary powers of 10.  Entry */
  30.     10., /* is 10^2^i.  Used to convert decimal */
  31.     100., /* exponents into floating-point numbers. */
  32.     1.0e4,
  33.     1.0e8,
  34.     1.0e16,
  35.     1.0e32,
  36.     1.0e64,
  37.     1.0e128,
  38.     1.0e256
  39. };
  40. /*
  41.  *----------------------------------------------------------------------
  42.  *
  43.  * strtod --
  44.  *
  45.  * This procedure converts a floating-point number from an ASCII
  46.  * decimal representation to internal double-precision format.
  47.  *
  48.  * Results:
  49.  * The return value is the double-precision floating-point
  50.  * representation of the characters in string.  If endPtr isn't
  51.  * NULL, then *endPtr is filled in with the address of the
  52.  * next character after the last one that was part of the
  53.  * floating-point number.
  54.  *
  55.  * Side effects:
  56.  * None.
  57.  *
  58.  *----------------------------------------------------------------------
  59.  */
  60. double
  61. strtod(string, endPtr)
  62.     CONST char *string; /* A decimal ASCII floating-point number,
  63.  * optionally preceded by white space.
  64.  * Must have form "-I.FE-X", where I is the
  65.  * integer part of the mantissa, F is the
  66.  * fractional part of the mantissa, and X
  67.  * is the exponent.  Either of the signs
  68.  * may be "+", "-", or omitted.  Either I
  69.  * or F may be omitted, or both.  The decimal
  70.  * point isn't necessary unless F is present.
  71.  * The "E" may actually be an "e".  E and X
  72.  * may both be omitted (but not just one).
  73.  */
  74.     char **endPtr; /* If non-NULL, store terminating character's
  75.  * address here. */
  76. {
  77.     int sign, expSign = FALSE;
  78.     double fraction, dblExp, *d;
  79.     register CONST char *p;
  80.     register int c;
  81.     int exp = 0; /* Exponent read from "EX" field. */
  82.     int fracExp = 0; /* Exponent that derives from the fractional
  83.  * part.  Under normal circumstatnces, it is
  84.  * the negative of the number of digits in F.
  85.  * However, if I is very long, the last digits
  86.  * of I get dropped (otherwise a long I with a
  87.  * large negative exponent could cause an
  88.  * unnecessary overflow on I alone).  In this
  89.  * case, fracExp is incremented one for each
  90.  * dropped digit. */
  91.     int mantSize; /* Number of digits in mantissa. */
  92.     int decPt; /* Number of mantissa digits BEFORE decimal
  93.  * point. */
  94.     CONST char *pExp; /* Temporarily holds location of exponent
  95.  * in string. */
  96.     /*
  97.      * Strip off leading blanks and check for a sign.
  98.      */
  99.     p = string;
  100.     while (isspace(UCHAR(*p))) {
  101. p += 1;
  102.     }
  103.     if (*p == '-') {
  104. sign = TRUE;
  105. p += 1;
  106.     } else {
  107. if (*p == '+') {
  108.     p += 1;
  109. }
  110. sign = FALSE;
  111.     }
  112.     /*
  113.      * Count the number of digits in the mantissa (including the decimal
  114.      * point), and also locate the decimal point.
  115.      */
  116.     decPt = -1;
  117.     for (mantSize = 0; ; mantSize += 1)
  118.     {
  119. c = *p;
  120. if (!isdigit(c)) {
  121.     if ((c != '.') || (decPt >= 0)) {
  122. break;
  123.     }
  124.     decPt = mantSize;
  125. }
  126. p += 1;
  127.     }
  128.     /*
  129.      * Now suck up the digits in the mantissa.  Use two integers to
  130.      * collect 9 digits each (this is faster than using floating-point).
  131.      * If the mantissa has more than 18 digits, ignore the extras, since
  132.      * they can't affect the value anyway.
  133.      */
  134.     
  135.     pExp  = p;
  136.     p -= mantSize;
  137.     if (decPt < 0) {
  138. decPt = mantSize;
  139.     } else {
  140. mantSize -= 1; /* One of the digits was the point. */
  141.     }
  142.     if (mantSize > 18) {
  143. fracExp = decPt - 18;
  144. mantSize = 18;
  145.     } else {
  146. fracExp = decPt - mantSize;
  147.     }
  148.     if (mantSize == 0) {
  149. fraction = 0.0;
  150. p = string;
  151. goto done;
  152.     } else {
  153. int frac1, frac2;
  154. frac1 = 0;
  155. for ( ; mantSize > 9; mantSize -= 1)
  156. {
  157.     c = *p;
  158.     p += 1;
  159.     if (c == '.') {
  160. c = *p;
  161. p += 1;
  162.     }
  163.     frac1 = 10*frac1 + (c - '0');
  164. }
  165. frac2 = 0;
  166. for (; mantSize > 0; mantSize -= 1)
  167. {
  168.     c = *p;
  169.     p += 1;
  170.     if (c == '.') {
  171. c = *p;
  172. p += 1;
  173.     }
  174.     frac2 = 10*frac2 + (c - '0');
  175. }
  176. fraction = (1.0e9 * frac1) + frac2;
  177.     }
  178.     /*
  179.      * Skim off the exponent.
  180.      */
  181.     p = pExp;
  182.     if ((*p == 'E') || (*p == 'e')) {
  183. p += 1;
  184. if (*p == '-') {
  185.     expSign = TRUE;
  186.     p += 1;
  187. } else {
  188.     if (*p == '+') {
  189. p += 1;
  190.     }
  191.     expSign = FALSE;
  192. }
  193. if (!isdigit(UCHAR(*p))) {
  194.     p = pExp;
  195.     goto done;
  196. }
  197. while (isdigit(UCHAR(*p))) {
  198.     exp = exp * 10 + (*p - '0');
  199.     p += 1;
  200. }
  201.     }
  202.     if (expSign) {
  203. exp = fracExp - exp;
  204.     } else {
  205. exp = fracExp + exp;
  206.     }
  207.     /*
  208.      * Generate a floating-point number that represents the exponent.
  209.      * Do this by processing the exponent one bit at a time to combine
  210.      * many powers of 2 of 10. Then combine the exponent with the
  211.      * fraction.
  212.      */
  213.     
  214.     if (exp < 0) {
  215. expSign = TRUE;
  216. exp = -exp;
  217.     } else {
  218. expSign = FALSE;
  219.     }
  220.     if (exp > maxExponent) {
  221. exp = maxExponent;
  222. errno = ERANGE;
  223.     }
  224.     dblExp = 1.0;
  225.     for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
  226. if (exp & 01) {
  227.     dblExp *= *d;
  228. }
  229.     }
  230.     if (expSign) {
  231. fraction /= dblExp;
  232.     } else {
  233. fraction *= dblExp;
  234.     }
  235. done:
  236.     if (endPtr != NULL) {
  237. *endPtr = (char *) p;
  238.     }
  239.     if (sign) {
  240. return -fraction;
  241.     }
  242.     return fraction;
  243. }