9

私はこの単純なコード行を持っています:

float val = 123456.123456;

この値を出力するか、スコープを調べると、値 123456.13 が格納されます

わかりました。ポイントの後のすべての数字を 4 バイトに格納することはできませんが、なぜポイントの後に 13 になるのでしょうか? 12じゃないの?

(win32 で vc++ 2010 Express を使用)

4

5 に答える 5

10

バイナリでは、123456.123456 は 11110001001000000.000111111001... (無限) です。11110001001000000.001 または 123456.125 に丸められます。印刷すると、 123456.13に丸められます。

于 2012-02-17T13:24:40.000 に答える
8

に格納されている値valは に等しい123456.125です。.13丸めているため、次のようになります。

float val = 123456.123456;
printf("%.4f %.2f\n", val, val);

出力:123456.1250 123456.13

この場合、切り捨てを避けるために double を使用する必要があります。コンパイラは、「警告 C4305: 'initializing': truncation from 'double' to 'float'」 という警告も表示する必要があります。

于 2012-02-17T13:22:30.617 に答える
7

float として表される場合、数値は 16 の指数を持ちます (つまり、値はその仮数に 2^16 を掛けたもの、つまり 65536 です)。仮数は次のようになります。

123456.123456 / 65536 = 1.8837909462890625

32 ビットの float に収まるように、仮数は 23 ビットに切り捨てられるため、 になり1.883791ます。を掛け直す65536と となる123456.125

5小数点の後の 3 番目の位置にある に注意してください。使用した C++ の出力ルーチンによって切り上げられ、最終的な数値は のようになります123456.13

EDIT丸めの説明:(Rick Reganのコメント)

丸めは、最初に 2 進数 (24 ビット)、10 進数から 2 進数への変換、次に 10 進数への変換で行われprintfます。格納された値は 1.1110001001000000001 x 2^16 = 1.8837909698486328125 x 2^16 = 123456.125 です。123456.13 として出力されますが、これは、Visual C++ が「0 から半分離れて丸める」丸めを使用するためです。

Rick にも、このテーマに関する優れた記事があります。

他の数値とその float 表現を試してみたい場合は、非常に便利な IEEE-754 電卓をご覧ください。

于 2012-02-17T13:26:44.960 に答える
2

それは完全にコンパイラに依存しています。GCCで確認してください。xxx.12 である必要があります。

于 2012-02-17T13:17:04.267 に答える
2

の値を出力してみてくださいstd::numeric_limits<float>::digits10。これは、浮動小数点数が 10 進法でどれだけの精度を持っているかを大まかに表したものです。それを超えようとしているため、精度が失われています (つまり、有効桁数を超える桁は実際には意味がありません)。

たとえば、numeric_limits<double>::digits10 の意味は何ですか

于 2012-02-17T13:15:43.330 に答える