「float」と「double」の精度


155

コード

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の有効数字がないのはなぜですか?

回答:


146

Cの浮動小数点数はIEEE 754エンコーディングを使用します。

このタイプのエンコーディングは、符号、仮数、および指数を使用します。

このエンコーディングのため、多くの数値は、それらを格納できるように小さな変更が加えられます。

また、有効桁数は10進数ではなく2進数であるため、多少異なる場合があります。

単精度(float)は、23ビットの仮数、8ビットの指数、および1サインビットを提供します。

倍精度(double)は、52ビットの仮数、11ビットの指数、および1つの符号ビットを提供します。


4
C99は、以前はコンパイラ次第でした。
アランGeleynse

21
-1このステートメントは露骨に誤りです:「このエンコーディングのため、値が変更されないことを保証することはできません。」
R .. GitHub ICE HELPING ICEを停止する'23

16
@Alan:C99はIEEE浮動小数点を必要としません。それはそれをお勧めします。
R .. GitHub ICE HELPING ICEを停止する'23

4
@アラン:R ..は正しいです。付録F(IEEE-754バインディングを指定)は規範的ですが、実装で定義されている場合にのみ有効です__STDC_IEC_559__。そのマクロを定義しない実装は、IEEE-754に準拠しなくても自由です。
スティーブンキャノン

12
@Alan:下のIEEE 754、簡単な値に変化がないことを保証します0.50.046875または0.376739501953125その小数表現対が。(これらはすべて仮数に分子近似、指数に分母近似の2を底とする対数有理数
です

42

倍精度浮動小数点数は常に16桁の有効数字を持っていますが、浮動小数点数は常に7桁の有効数字を持っていますか?

いいえ。倍精度浮動小数点数には常に53の有効ビットがあり、浮動小数点数には常に24の有効ビットがあります(非正規化数、無限大、およびNaN値を除きますが、これらは別の質問の対象です)。これらはバイナリ形式であり、2進数(ビット)による表現の精度についてのみ明確に話すことができます。

これは、2進整数に何桁まで格納できるかという問題に似ています。符号なし32ビット整数は、32ビットまでの整数を格納できます。これは、任意の数の10進数字に正確にマッピングされません。 10桁の9桁を格納できますが、10桁の数値も多数格納できます。

ダブルスに14の有効数字がないのはなぜですか?

doubleのエンコードでは、64ビットを使用します(符号に1ビット、指数に11ビット、52の明示的な有効ビットと1つの暗黙のビット)。これは、floatを表すために使用されるビット数(32ビット)の2倍です。


15

float:仮数23ビット、指数8ビット、および符号1ビット。

double:仮数52ビット、指数11ビット、および符号1ビット。


11

これは通常、基数10ではなく、基数2の指数と仮数の両方の有意な数値に基づいています。ただし、C99標準でわかることから、浮動小数点数と倍精度浮動小数点数の精度は指定されていません(1と1 + 1E-5/ 1 + 1E-7区別可能です[ floatそしてdoubleそれぞれの]])。ただし、有効数字の数は実装者に委ねられます(内部で使用する基数も同様です。つまり、実装では、基数3の18桁の精度に基づいてそれを作成することもできます)。[1]

これらの値を知る必要がある場合、定数FLT_RADIXFLT_MANT_DIG(およびDBL_MANT_DIG/ LDBL_MANT_DIG)はfloat.hで定義されます。

これをa doubleと呼ぶ理由は、それを格納するために使用されるバイト数が浮動小数点数の2倍であるためです(ただし、これには指数と仮数の両方が含まれます)。IEEE 754標準(ほとんどのコンパイラで使用されます)は、指数よりも比較的多くのビットを仮数に割り当てます(の場合23〜9 float対の場合52〜12 double)。これは、精度が2倍を超える理由です。

1:セクション5.2.4.2.2(http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf


打ち間違え?C89は、最大でのイプシロンを必要とする1E-9ためdouble、ではありません1E-7
Rufflewind 2016年


4

それは正確にはありませんダブルので、どのように精度IEEE 754作品、およびバイナリは本当に小数にうまく変換されないので。興味があれば規格を見てください。


4

floatは浮動小数点数を表します。Cでは、総桁数の精度が7である場合にfloatデータ型が使用されます。例:-10進数 12.3546987は合計9桁であるため、フロートに格納できません。出力は12.354699として表示されます。つまり、最初の7桁は入力で入力されたとおりに表示され、8桁目は四捨五入されます。フロートタイプは値を表すことができます約1.5 x 10 ^(-45)から3.4 x 10 ^(38)の範囲です。メモリ割り当ての観点から、floatは単精度の32ビット浮動小数点データ型です。

floatとは異なり、doubleの精度は15から16桁です。doubleの範囲は5.0×10 ^(-345)から1.7×10 ^(308)です。バイト割り当ての点では、doubleは64ビットの浮動小数点データですタイプ。

この問題は、use.floatまたはdoubleで発生しますが、printfには影響しませんが、scanfの場合は、総数に応じて適切なデータ型が使用されます。浮動番号の桁数 これは入力から読み取られます。

したがって、データの精度を高めるには、floatよりもdoubleの方が適しています。

お役に立てれば。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.