Следующая функция dtoa
возвращает строку, которая без потерь конвертируется обратно в ту же double
.
Если переписать aisd
для тестирования всех ваших реализаций string
-to- float
, у вас будет переносимый вывод среди них.
// 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;
}
См. Не удалось получить NaN из функций MSVCRT strtod / sscanf / atof для проблемы MSVCRT NaN
.Если вам не нужно распознавать NaN
s, вы можете вывести бесконечность ("1e999"
), когда получите его.