strtod.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:4k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*
  2. ** An alternative implemtation of "strtod()" that is both
  3. ** simplier, and thread-safe.
  4. */
  5. #include <pthread.h>
  6. #include <ctype.h>
  7. #include <math.h>
  8. #ifdef TEST
  9. #  define strtod NewStrtod
  10. #include <stdio.h>
  11. #endif
  12. static double scaler10[] = {
  13.   1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90
  14. };
  15. static double scaler1[] = {
  16.   1.0, 10.0, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9
  17. };
  18. static double pastpoint[] = {
  19.   1e-1,  1e-2,  1e-3,  1e-4,  1e-5,  1e-6,  1e-7,  1e-8,  1e-9,
  20.   1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18,  1e-19,
  21.   1e-20, 1e-21, 1e-22, 1e-23, 1e-24, 1e-25, 1e-26, 1e-27, 1e-28,  1e-29,
  22.   1e-30, 1e-31, 1e-32, 1e-33, 1e-34, 1e-35, 1e-36, 1e-37, 1e-38,  1e-39,
  23.   1e-40, 1e-41, 1e-42, 1e-43, 1e-44, 1e-45, 1e-46, 1e-47, 1e-48,  1e-49,
  24.   1e-50, 1e-51, 1e-52, 1e-53, 1e-54, 1e-55, 1e-56, 1e-57, 1e-58,  1e-59,
  25. };
  26. #ifndef DBL_MAX
  27. #define DBL_MAX 1.7976931348623157e+308
  28. #endif
  29. double strtod(const char *zNum, char **pzEnd){
  30.   double rResult = 0.0;
  31.   int isNegative = 0;
  32.   while( isspace(*zNum) ){
  33.     zNum++;
  34. }
  35.   if( *zNum=='-' ){
  36.     zNum++;
  37.     isNegative = 1;
  38.   }else if( *zNum=='+' ){
  39.     zNum++;
  40. }
  41.   while( isdigit(*zNum) ){
  42.     rResult = rResult*10.0 + (*zNum - '0');
  43.     zNum++;
  44. }
  45.   if( *zNum=='.' ){
  46.     int n = 0;
  47.     zNum++;
  48.     while( isdigit(*zNum) ){
  49.       if( n<sizeof(pastpoint)/sizeof(pastpoint[0]) ){
  50.         rResult += pastpoint[n] * (*zNum - '0');
  51.         n++;
  52. }
  53.       zNum++;
  54. }
  55. }
  56.   if( *zNum=='e' || *zNum=='E' ){
  57.     int expVal = 0;
  58.     int isNegExp = 0;
  59.     const char *zExpStart = zNum;
  60.     zNum++;
  61.     if( *zNum=='-' ){
  62.       isNegExp = 1;
  63.       zNum++;
  64.     }else if( *zNum=='+' ){
  65.       zNum++;
  66. }
  67.     if( !isdigit(*zNum) ){
  68.       zNum = zExpStart;
  69.     }else{
  70.       double scaler = 1.0;
  71.       while( isdigit(*zNum) ){
  72.         expVal = expVal*10 + *zNum - '0';
  73.         zNum++;
  74. }
  75.       if( expVal >= 1000 ){
  76.         if( isNegExp ){
  77.           rResult = 0.0;
  78.         }else{
  79.           rResult = DBL_MAX;
  80. }
  81.         goto done;
  82. }
  83.       while( expVal >= 100 ){
  84.         scaler *= 1.0e100;
  85.         expVal -= 100;
  86. }
  87.       scaler *= scaler10[expVal/10]*scaler1[expVal%10];
  88.       if( isNegExp ){
  89.         scaler = 1.0/scaler;
  90. }
  91.       rResult *= scaler;
  92. }
  93. }
  94. done:
  95.   if( pzEnd ){
  96.     *pzEnd = (char *)zNum;
  97. }
  98.   if( isNegative && rResult!=0.0 ){
  99.     rResult = -rResult;
  100. }
  101.   return rResult;
  102. }
  103. double atof(const char *nptr)
  104. {
  105.   return (strtod(nptr, 0));
  106. }
  107. #ifdef TEST
  108. #undef strtod
  109. double strtod(const char*,char**);
  110. double NewStrtod(const char*,char**);
  111. int main(int argc, char **argv){
  112.   int nTest = 0;
  113.   int nFail = 0;
  114.   int nBigFail = 0;
  115.   char zBuf[1000];
  116.   while( fgets(zBuf,sizeof(zBuf),stdin) ){
  117.     double old, new;
  118.     char *zTailOld, *zTailNew;
  119.     int i;
  120.     for(i=0; zBuf[i] && zBuf[i]!='n'; i++){}
  121.     zBuf[i] = 0;
  122. #if TEST==1
  123.     printf("Input line: [%s]n",zBuf);
  124.     old = strtod(zBuf,&zTailOld);
  125.     printf("value=%gn",old);
  126.     printf("Old:        0x%08x%08x  tail=[%s]n",
  127.            ((int*)&old)[1], ((int*)&old)[0], zTailOld);
  128.     new = NewStrtod(zBuf,&zTailNew);
  129.     printf("value=%gn",new);
  130.     printf("New:        0x%08x%08x  tail=[%s]nn",
  131.            ((int*)&new)[1], ((int*)&new)[0], zTailNew);
  132. #else
  133.     old = strtod(zBuf,&zTailOld);
  134.     new = NewStrtod(zBuf,&zTailNew);
  135.     nTest++;
  136.     if( strcmp(zTailOld,zTailNew) 
  137.         || ((int*)&old)[0]!=((int*)&new)[0]
  138.         || ((int*)&old)[1]!=((int*)&new)[1]
  139.         ){
  140.       int olda, oldb, newa, newb;
  141.       nFail++;
  142.       olda = ((int*)&old)[1];
  143.       oldb = ((int*)&old)[0];
  144.       newa = ((int*)&new)[1];
  145.       newb = ((int*)&new)[0];
  146.       if( olda!=newa || abs(oldb-newb)>2 ){
  147.         nBigFail++;
  148.         printf("******* Big failure n");
  149. }
  150.       printf("Input = [%s]n",zBuf);
  151.       printf("old:   val=%g   0x%08x%08x  tail=[%s]n",
  152.              old, olda, oldb, zTailOld);
  153.       printf("new:   val=%g   0x%08x%08x  tail=[%s]nn",
  154.              new, newa, newb, zTailNew);
  155. }
  156. #endif
  157. }
  158.   printf("Out of %d tests, %d failures and %d big failursn",
  159.          nTest,nFail, nBigFail);
  160. }
  161. #endif