The following dtoa function returns a string that, without loss, converts back to the same double .
If you rewrite aisd to test all your string float implementations, you will have portable output among them.
// Return whether a string represents the given double. int aisd(double f, char* s) { double r; sscanf(s, "%lf", &r); return r == f; } // Return the shortest lossless string representation of an IEEE double. // Guaranteed to fit in 23 characters (including the final '\0'). char* dtoa(char* res, double f) { int i, j, lenF = 1e9; char fmt[8]; int e = floor(log10(f)) + 1; if (f > DBL_MAX) { sprintf(res, "1e999"); return res; } // converts to Inf if (f < -DBL_MAX) { sprintf(res, "-1e999"); return res; } // converts to -Inf if (isnan(f)) { sprintf(res, "NaN"); return res; } // NaNs don't work under MSVCRT // compute the shortest representation without exponent ("123000", "0.15") if (!f || e>-4 && e<21) { for (i=0; i<=20; i++) { sprintf(fmt, "%%.%dlf", i); sprintf(res, fmt, f); if (aisd(f, res)) { lenF = strlen(res); break; } } } if (!f) return res; // compute the shortest representation with exponent ("123e3", "15e-2") for (i=0; i<19; i++) { sprintf(res, "%.0lfe%d", f * pow(10,-e), e); if (aisd(f, res)) break; j = strlen(res); if (j >= lenF) break; while (res[j] != 'e') j--; res[j-1]--; if (aisd(f, res)) break; // try mantissa -1 res[j-1]+=2; if (aisd(f, res)) break; // try mantissa +1 e--; } if (lenF <= strlen(res)) sprintf(res, fmt, f); return res; }
See Unable to get NaN from MSVCRT strtod / sscanf / atof functions for MSVCRT NaN problem. If you do not need to recognize NaN s, you can output infinity ( "1e999" ) when you receive it.
source share