NaN
をWindows CRT string
からfloat
に変換する方法はありますか?MSVCRT strtod/sscanf/atof関数からNaNを取得できません
理由:ノー情報損失(strtod
、sscanf
またはatof
元float
を返す)とCでのIEEE float
string
へのコンバータを書いては丸めモードは変更されません提供。
私はMinGWまたはVisual C++の下にあるので、これらの呼び出しはMSVC++ランタイムに移動します。問題は、特別な値(たとえば"Inf"
または"NaN"
など)を解析することができないということです。 Inf
はOKです(これは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;
}
元の番号をbit-for-bitにするか、ペイロードビットを保持する必要はありません。どちらも真実ではありません。また、エンコーダ/デコーダのペアのこの機能は、「ラウンドトリップ」と呼ばれ、無損失ではありません。 * Lossless *はエンコーディング自体を参照するものであり、エンコーディング自体を作成する機能ではありません。 –
@BenVoigt入力いただきありがとうございました。実際には、ペイロードビットを保存する必要がありました。 –
'boost :: math :: nonfinite_num_get/put'を使った解決策:http://www.boost.org/doc/libs/1_47_0/libs/math/doc/sf_and_dist/html/math_toolkit/utils/fp_facets/intro.html –