result of convert string to double is inconsistent with strtod

24 views Asked by At

I implemented a function StringToDouble for converting string to double,but when I test my function and standard strtod function with the same string,the result is different,I dont know why this happened,is it a problem with precision when doing arithmetic with double? and How can I fix my function so it will generate the same result as strtod? thanks. this is StringToDouble I implemented

    bool StringToDouble(const char *p, double &num) {
    int frac;
    double sign, value, scale;
    bool canConvert = false;
    if (p == NULL || *p == 0) {
        num = 0;
        return false;
    }
    // Skip leading white space, if any.
    while (white_space(*p)) {
        p += 1;
    }

    // Get sign, if any.
    sign = 1.0;
    if (*p == '-') {
        sign = -1.0;
        p += 1;
    } else if (*p == '+') {
        p += 1;
    }
    if (valid_digit(*p)) canConvert = true;
    // Get digits before decimal point or exponent, if any.
    for (value = 0.0; valid_digit(*p); p += 1) {
        value = value * 10.0 + (*p - '0');
    }
   
    // Get digits after decimal point, if any.
    if (*p == '.') {
        double pow10 = 10.0;
        p += 1;
        if (valid_digit(*p)) canConvert = true;
        while (valid_digit(*p)) {
            value += (*p - '0') / pow10;
            pow10 *= 10.0;
            p += 1;
          
        }
    }

    // Handle exponent, if any.
    frac = 0;
    scale = 1.0;
    if ((*p == 'e') || (*p == 'E')) {
        unsigned int expon;

        // Get sign of exponent, if any.
        p += 1;
        if (*p == '-') {
            frac = 1;
            p += 1;
        } else if (*p == '+') {
            p += 1;
        }

        // Get digits of exponent, if any.
        for (expon = 0; valid_digit(*p); p += 1) {
            expon = expon * 10 + (*p - '0');
        }
        if (expon > 308) expon = 308;

        // Calculate scaling factor.

        while (expon >= 50) {
            scale *= 1E50;
            expon -= 50;
        }
        while (expon >= 8) {
            scale *= 1E8;
            expon -= 8;
        }
        while (expon > 0) {
            scale *= 10.0;
            expon -= 1;
        }
    }

    // Return signed and scaled floating point result.
    if (!canConvert) {
        num = 0;
        return false;
    } else {
        num = sign * (frac ? (value / scale) : (value * scale));
        return true;
    }
}

this is the code I use for testing

const char *p = "3e+100";
double d;
StringToDouble(p, d);
double dd = strtod(p, nullptr);
if (d == dd) {
    cout.precision(17);
    cout << dd << endl
         << d;
} else {
    cout.precision(17);
    cout << "not equal\n";
    cout << dd << endl
         << d;
}

the output is

not equal
2.9999999999999999e+100
3.0000000000000006e+100

I also tested other strings,some get the same result with strtod,some not,all the cases with exponent get different result.

0

There are 0 answers