Cの type の説明でfloat
は、有効桁数は6
です。でも、
float f = 12345.6;
printf() を使用して印刷しても は印刷されず12345.6
、 が印刷されます12345.599609
。double
では、浮動小数点型の「有効桁数 6 桁」(または「」の場合は「15 桁」) は何を意味するのでしょうか?
Cの type の説明でfloat
は、有効桁数は6
です。でも、
float f = 12345.6;
printf() を使用して印刷しても は印刷されず12345.6
、 が印刷されます12345.599609
。double
では、浮動小数点型の「有効桁数 6 桁」(または「」の場合は「15 桁」) は何を意味するのでしょうか?
6 桁の有効数字は、最大誤差が約 +/- 0.0001% であることを意味します。単一の float 値には、実際には約 7.2 桁の精度があります ( source )。これは、エラーが約 +/- 12345.6/10^7 = 0.00123456 であることを意味します。あなたのエラー(0.000391)のオーダーです。
標準によると、すべての 10 進数を正確にメモリに格納できるわけではありません。表現のサイズによっては、エラーが特定の最大値に達する可能性があります。float
これは(0.0001%
有効数字 6 桁 = 10^-6
= 10^-4 %
) です。
あなたの場合、エラーは(12345.6 - 12345.599609) / 12345.6 = 3.16e-08
フロートの最大エラーよりもはるかに低くなっています。
あなたが見ているのは、実際には有効数字の問題ではありませんが、コンピューター上の数値は 2 進数で格納され、3/5 (= 0.6) の有限の 2 進数表現がないという事実です。バイナリの 3/5 は 0.100110011001... のように見え、「1001」パターンが永遠に繰り返されます。このシーケンスは 0.599999... の繰り返しに相当します。精度に関連するエラーが発生する前に、実際には小数点の右側にある小数点以下 3 桁まで到達しています。
これは、1/3 の 10 進法の有限表現が存在しないことに似ています。0.3333 が永久に繰り返されます。
ここでの問題は、数値を float に格納できることを保証できないことです。IEEE 754で説明されているように、この数値を仮数、基数、指数で表す必要があります。数字printf(...)
は、格納された実際の浮動小数点数であることを示しています。浮動小数点数の有効桁数は保証できません。