41
float f = 0.7;
if( f == 0.7 )
    printf("equal");
else
    printf("not equal");

なぜ出力not equalですか?

なぜこれが起こるのですか?

4

8 に答える 8

56

これは、あなたの声明で

  if(f == 0.7)

0.7 は double として扱われます。0.7f を試して、値が float として扱われるようにします。

  if(f == 0.7f)

しかし、Michael が以下のコメントで示唆したように、浮動小数点値が正確に等しいかどうかをテストするべきではありません。

于 2009-12-03T11:45:37.557 に答える
14

既存のものを補完するこの答え:0.7はフロート(またはダブル)として正確に表現できないことに注意してください。正確に表現されていれば、floatに変換してからdoubleに戻すときに情報が失われることはなく、この問題は発生しません。

特に、次のように設定されたモードで実行時に丸めが行われるかどうかに関して標準が非常にあいまいな場合は、正確に表すことができないリテラル浮動小数点定数に対してコンパイラ警告が必要であると主張することもできます。そのとき、または別の丸めモードでのコンパイル時に。

正確に表すことができるすべての非整数は5、最後の10進数です。残念ながら、その逆は当てはまりません。一部の数値は5最後の10進数であり、正確に表すことができません。小さな整数はすべて正確に表すことができ、2の累乗で除算すると、非正規化数の領域に入らない限り、表すことができる別の数値に変換されます。

于 2009-12-03T11:53:46.263 に答える
14

まず、浮動小数点数の中を見てみましょう。私は 0.1f を取り、それは 4 バイトの長さ (binary32) で、16 進数では
3D CC CC CDです。
標準のIEEE 754で10進数に変換するには、次のようにする必要があります。

ここに画像の説明を入力
バイナリ 3D CC CC CD は
0 01111011 1001100 11001100 11001101
ここで最初の桁は符号ビットです。0 は (-1)^0 を意味し、数値が正であることを意味します。
2 番目の 8 ビットは指数です。2 進数では 01111011 - 10 進数では 123 です。しかし、実際の指数は 123-127 (常に 127)= -4です。これは、取得する数値に 2^ (-4) を掛ける必要があることを意味します。
最後の 23 バイトは有効桁数の精度です。最初のビットに 1/ (2^1) (0.5) を掛け、2 番目のビットに 1/ (2^2) (0.25) を掛けます。ここで得られるもの:


ここに画像の説明を入力 ここに画像の説明を入力

すべての数字 (2 の累乗) を加算し、それに 1 を加算する必要があります (標準では常に 1)。これは
1,60000002384185791015625 です
。では、この数値に 2^ (-4) を掛けましょう。これは指数からのものです。上記の数値を2の 4 倍 で割ります :
0,100000001490116119384765625



今第二部。10 進数から 2 進数への変換。

**
数値 0.1 を取り
ます。整数部分がないので楽です。最初の符号ビット - 0 です。指数と有効桁数の精度を計算します。ロジックは 2 つの整数 (0.1*2=0.2) を乗算し、それが 1 より大きい場合は減算して続行します。 数値は .00011001100110011001100110011 で、標準では 1 になる前に左にシフトする必要があります。ご覧のように、指数(127-4= 123 ) を計算するこの数値から 4 つのシフトが必要です。そして有効桁数の精度は10011001100110011001100になりました (失われたビットがあります)。 これで整数です。符号ビット0の指数は 123 ( 01111011 ) で、有効桁数の精度は10011001100110011001100 です。
ここに画像の説明を入力


全体は
00111101110011001100110011001100です。前の章の
00111101110011001100110011001101 と比較してみましょう
。数字を切り捨てているからです。CPU とコンパイラは、有効桁数の精度が保持できず、最後のビットを 1 に設定した後のものであることを認識しています。

于 2016-07-12T09:21:44.923 に答える
1

The problem you're facing is, as other commenters have noted, that it's generally unsafe to test for exact equivalency between floats, as initialization errors, or rounding errors in calculations can introduce minor differences that will cause the == operator to return false.

A better practice is to do something like

float f = 0.7;
if( fabs(f - 0.7) < FLT_EPSILON )
    printf("equal");
else
    printf("not equal");

Assuming that FLT_EPSILON has been defined as an appropriately small float value for your platform.

Since the rounding or initialization errors will be unlikely to exceed the value of FLT_EPSILON, this will give you the reliable equivalency test you're looking for.

于 2015-09-21T00:24:25.920 に答える