コード
float x = 3.141592653589793238;
double z = 3.141592653589793238;
printf("x=%f\n", x);
printf("z=%f\n", z);
printf("x=%20.18f\n", x);
printf("z=%20.18f\n", z);
あなたに出力を与えるでしょう
x=3.141593
z=3.141593
x=3.141592741012573242
z=3.141592653589793116
3行目の出力741012573242
はゴミで、4行目の116
はゴミです。倍精度は常に16の有効数字を持っていますがフロートは常に7の有効数字を持っていますか?ダブルスに14の有効数字がないのはなぜですか?
Cの浮動小数点数は、 IEEE 754 エンコードを使用します。
このタイプのエンコーディングは、符号、仮数部、および指数を使用します。
このエンコーディングのために、多くの数はそれらが格納されることを可能にするために小さな変化を持つでしょう。
また、有効数字の桁数は、10進数ではなく2進表記であるため、わずかに変わる可能性があります。
単精度(float)は、23ビットの仮数、8ビットの指数、1ビットの符号を与えます。
倍精度(double)では、52ビットの仮数、11ビットの指数、および1符号ビットが得られます。
倍精度は常に16の有効数字を持っていますがフロートは常に7の有効数字を持っていますか?
ダブルは常に53の有効ビットを持ち、フロートは常に24の有効ビットを持つ(非正規数、無限大、およびNaN値を除くが、これらは異なる質問の対象です)。これらは2進形式であり、2進数(ビット)に関してそれらの表現の精度について明確に話すことができるだけです。
これは、2進整数に格納できる桁数の問題に似ています。符号なし32ビット整数は、最大32ビットの整数を格納できます。これは、小数点以下の桁数に正確には対応しません。 9桁の10進数を保存できますが、10桁の数字を多数保存することもできます。
ダブルスに14の有効数字がないのはなぜですか?
Doubleの符号化では64ビット(符号用に1ビット、指数用に11ビット、明示的に52ビット、暗黙的に1ビット)を使用します。これはdoubleビット数です。 float(32ビット)を表すために使用されます。
float:23ビットの仮数、8ビットの指数、1ビットの符号
double:仮数52ビット、指数11ビット、符号1ビット。
通常、基数10ではなく基数2の指数と仮数の両方の有効数字に基づいています。ただし、C99標準でわかることから、floatとdoubleの精度は指定されていません(1と1 + 1E-5
/1 + 1E-7
は区別できる[float
とdouble
はそれぞれ区別可能))。ただし、有効数字の数は実装者に委ねられています(また、内部でどの基数を使用するか、つまり、実装は基数3の18桁の精度に基づいて決定することもできます)。 [1]
これらの値を知る必要がある場合、定数FLT_RADIX
およびFLT_MANT_Dig
(およびDBL_MANT_Dig
/LDBL_MANT_Dig
)はfloat.hで定義されます。
double
と呼ばれる理由は、格納に使用されるバイト数が浮動小数点数の2倍であるためです(ただし、これには指数と仮数の両方が含まれます)。 IEEE 754標準(ほとんどのコンパイラーで使用)は、仮数部に指数部よりも比較的多くのビットを割り当てます(float
の場合は23から9対double
の場合は52から12)。倍以上。
1:セクション5.2.4.2.2( http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf )
Floatは23ビットの精度を持ち、doubleは52の精度を持ちます。
IEEE 754 のしくみや、バイナリは実際には10進数に変換できないため、正確には倍精度ではありません。興味があれば、規格を見てください。