// // Simple and fast atof (ascii to float) function. // // - Executes about 5x faster than standard MSCRT library atof(). // - An attractive alternative if the number of calls is in the millions. // - Assumes input is a proper integer, fraction, or scientific format. // - Matches library atof() to 15 digits (except at extreme exponents). // - Follows atof() precedent of essentially no error checking. // // 09-May-2009 Tom Van Baak (tvb) www.LeapSecond.com // #define white_space(c) ((c) == ' ' || (c) == '\t') #define valid_digit(c) ((c) >= '0' && (c) <= '9') double atof (const char *p) { int frac; double sign, value, scale; // 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; } // Get digits before decimal point or exponent, if any. value = 0.0; while (valid_digit(*p)) { value = value * 10.0 + (*p - '0'); p += 1; } // Get digits after decimal point, if any. if (*p == '.') { double pow10 = 10.0; p += 1; while (valid_digit(*p)) { value += (*p - '0') / pow10; pow10 *= 10.0; p += 1; } } // Handle exponent, if any. scale = 1.0; if ((*p == 'e') || (*p == 'E')) { unsigned int expon; p += 1; // Get sign of exponent, if any. frac = 0; if (*p == '-') { frac = 1; p += 1; } else if (*p == '+') { p += 1; } // Get digits of exponent, if any. expon = 0; while (valid_digit(*p)) { expon = expon * 10 + (*p - '0'); p += 1; } 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. return sign * (frac ? (value / scale) : (value * scale)); }