Есть ли способ получить NaN
s от функций Windows CRT string
до float
?
Почему: Я пишу IEEE *Преобразователь из 1009 * в string
в C без потери информации (strtod
, sscanf
или atof
возвращает оригинал float
) при условии, что режим округления не изменяется.
Япод MinGW или Visual C ++, поэтому эти вызовы переходят во время выполнения MSVC ++.Проблема в том, что я не могу заставить его анализировать какие-либо специальные значения (например, "Inf"
или "NaN"
).Inf
в порядке (возвращается после анализа значения, которое не помещается в float
, например "1e999"
).
/* Return the shortest string representation of a float with a successful scanf round-trip.
* Guaranteed to fit in 13 chars (including the final '\0').
*/
char* ftoa(char* res, float f) {
float r = 0;
int i, j, len, e = floor(log10(f)) + 1;
char fmt[8];
union { float f; int32_t i; } u = { f } ;
if (f > FLT_MAX) { sprintf(res, "1e999"); return res; }
if (f < -FLT_MAX) { sprintf(res, "-1e999"); return res; }
if ((u.i & 0x7F800000) == 0x7F800000) { // NaN
sprintf(res, u.i == 0x7FC00000 ? "%sNaN" : "%sNaN%d", u.i<0 ? "-" : "", u.i & 0x7FFFFF);
return res;
}
// compute the shortest string without exponent ("123000", "0.15")
if (!f || e>-4 && e<10) {
for (i=0; i<=10; i++) {
sprintf(fmt, "%%.%df", i);
sprintf(res, fmt, f);
sscanf(res, "%f", &r); if (r==f) break;
}
}
if (r==f) len = strlen(res);
else len = 1e9;
if (!f) return res; // handle 0 and -0
// compute the shortest string with exponent ("123e3", "15e-2")
for (i=0; i<9; i++) {
sprintf(res, "%.0fe%d", f * pow(10,-e), e); sscanf(res, "%f", &r); if (r==f) break;
j = strlen(res); if (j >= lenF) break;
while (res[j] != 'e') j--;
res[j-1]--; sscanf(res, "%f", &r); if (r==f) break; // try +-1
res[j-1]+=2; sscanf(res, "%f", &r); if (r==f) break;
e--;
}
if (len <= strlen(res)) sprintf(res, fmt, f);
return res;
}