将ACII码转为浮点数

今天看到这样一些代码,情不自禁的把它写入博客,想要好好研究一下这段代码,很优秀的代码,我要研究他们是怎么写出来的。

同时对自己寄予厚望,希望能够有帮助。呵呵
 * strtod.c --  *  * Source code for the "strtod" library procedure.  *  * Copyright (c) 1988-1993 The Regents of the University of California.  * Copyright (c) 1994 Sun Microsystems, Inc.  *  * See the file "license.terms" for information on usage and redistribution  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.  *  * RCS: @(#) $Id$  */

#include "tclInt.h" 
#ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef NULL #define NULL 0 #endif 
static const int maxExponent = 511;     /* Largest possible base 10 exponent. Any  * exponent larger than this will already  * produce underflow or overflow, so there's  * no need to worry about additional digits.  */
static const double powersOf10[] = {    /* Table giving binary powers of 10. Entry */
    10.,                        /* is 10^2^i. Used to convert decimal */
    100.,                       /* exponents into floating-point numbers. */
    1.0e4,
    1.0e8,
    1.0e16,
    1.0e32,
    1.0e64,
    1.0e128,
    1.0e256
};

/*  *----------------------------------------------------------------------  *  * strtod --  *  * This procedure converts a floating-point number from an ASCII  * decimal representation to internal double-precision format.  *  * Results:  * The return value is the double-precision floating-point  * representation of the characters in string. If endPtr isn't  * NULL, then *endPtr is filled in with the address of the  * next character after the last one that was part of the  * floating-point number.  *  * Side effects:  * None.  *  *----------------------------------------------------------------------  */

double
strtod(
    const char *string,         /* A decimal ASCII floating-point number,  * optionally preceded by white space. Must  * have form "-I.FE-X", where I is the integer  * part of the mantissa, F is the fractional  * part of the mantissa, and X is the  * exponent. Either of the signs may be "+",  * "-", or omitted. Either I or F may be  * omitted, or both. The decimal point isn't  * necessary unless F is present. The "E" may  * actually be an "e". E and X may both be  * omitted (but not just one). */
    char **endPtr)              /* If non-NULL, store terminating character's  * address here. */
{
    int sign, expSign = FALSE;
    double fraction, dblExp;
    const double *d;
    register const char *p;
    register int c;
    int exp = 0;                /* Exponent read from "EX" field. */
    int fracExp = 0;            /* Exponent that derives from the fractional  * part. Under normal circumstatnces, it is  * the negative of the number of digits in F.  * However, if I is very long, the last digits  * of I get dropped (otherwise a long I with a  * large negative exponent could cause an  * unnecessary overflow on I alone). In this  * case, fracExp is incremented one for each  * dropped digit. */
    int mantSize;               /* Number of digits in mantissa. */
    int decPt;                  /* Number of mantissa digits BEFORE decimal  * point. */
    const char *pExp;           /* Temporarily holds location of exponent in  * string. */

    /*  * Strip off leading blanks and check for a sign.  */

    p = string;
    while (isspace(UCHAR(*p))) {
        p += 1;
    }
    if (*p == '-') {
        sign = TRUE;
        p += 1;
    } else {
        if (*p == '+') {
            p += 1;
        }
        sign = FALSE;
    }

    /*  * Count the number of digits in the mantissa (including the decimal  * point), and also locate the decimal point.  */

    decPt = -1;
    for (mantSize = 0; ; mantSize += 1)
    {
        c = *p;
        if (!isdigit(c)) {
            if ((c != '.') || (decPt >= 0)) {
                break;
            }
            decPt = mantSize;
        }
        p += 1;
    }

    /*  * Now suck up the digits in the mantissa. Use two integers to collect 9  * digits each (this is faster than using floating-point). If the mantissa  * has more than 18 digits, ignore the extras, since they can't affect the  * value anyway.  */

    pExp  = p;
    p -= mantSize;
    if (decPt < 0) {
        decPt = mantSize;
    } else {
        mantSize -= 1;          /* One of the digits was the point. */
    }
    if (mantSize > 18) {
        fracExp = decPt - 18;
        mantSize = 18;
    } else {
        fracExp = decPt - mantSize;
    }
    if (mantSize == 0) {
        fraction = 0.0;
        p = string;
        goto done;
    } else {
        int frac1, frac2;

        frac1 = 0;
        for ( ; mantSize > 9; mantSize -= 1) {
            c = *p;
            p += 1;
            if (c == '.') {
                c = *p;
                p += 1;
            }
            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');
        }
        fraction = (1.0e9 * frac1) + frac2;
    }

    /*  * Skim off the exponent.  */

    p = pExp;
    if ((*p == 'E') || (*p == 'e')) {
        p += 1;
        if (*p == '-') {
            expSign = TRUE;
            p += 1;
        } else {
            if (*p == '+') {
                p += 1;
            }
            expSign = FALSE;
        }
        if (!isdigit(UCHAR(*p))) {
            p = pExp;
            goto done;
        }
        while (isdigit(UCHAR(*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 < 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) {
        if (exp & 01) {
            dblExp *= *d;
        }
    }
    if (expSign) {
        fraction /= dblExp;
    } else {
        fraction *= dblExp;
    }

  done:
    if (endPtr != NULL) {
        *endPtr = (char *) p;
    }

    if (sign) {
        return -fraction;
    }
    return fraction;
}

你可能感兴趣的:(c,String,null,Integer,processing,character)