2011-11-14 10 views
5

:Javaでは同じ条件、異なる結果Cで

float a = 1.3; 
if (a == 1.3) 
    printf("Hello c"); 
else 
    printf("Bye c"); 

//output: Bye c 

float a = 1.3; 
if (a == 1.3) 
    System.out.println("Hello java"); 
else 
    System.out.println("Bye java"); 

//output: Hello java 

なぜこれがそうですか?

+2

I 'あなたのコードにいくつかの[小さな修正](http://programmers.stackexchange.com/posts/119596/revisions)を行ったところ、元のコードがうまくいかなかったのです。あなたのコードが出力を生成するのを見たことがありますか、それともどこかからコピーしましたか? – yannis

答えて

21

"1.3"をバイナリ浮動小数点として正確に表すことはできません。

リテラル1.3を浮動小数点数に変換すると、浮動小数点数は1.3に近似しますが、厳密には1.3にはなりません。

Javaの場合、JVMは "1.3"を標準Java浮動小数点として解釈し、ほぼ同じ1.3に変換するので、あなたは幸運に思っていました。 2進数。 Cの場合、1.3では "double"と解釈され、通常のfloatよりも小数点以下1.3に近い2進浮動小数点に変換されます。

結論は、ストレージの小さな変化、計算の順番などがわずかに異なる結果になるため、フロートを等価にすることは絶対にしないことです。

if (a > 1.299 && a < 1.301) // something close to 1.3 
+7

ちょうど完全なニット・ピックになる:Cでは、 '1.3'は常にダブルです。 (単精度)浮動小数点数リテラルの構文は '1.3f'です。 – tdammers

+0

@tdammmers - ありがとう。私はこれがコンパイラ特有のものか標準のものであるかはわかりませんでした。 –

1

ちょうど私はあなたに簡単な類推を与えてみましょう、あなたは答えの周りにあなたの脳を包むのに役立つ:あなたは、常に「ブラケット」そうのような浮動小数点比較する必要があります。浮動小数点数はおおよその値です。多くの数字を正確に表すことはできません。小数点以下で6桁を使用するとします。

どのように1/3を表しますか? .333333が最善の方法です。しかし、今は3 * 1/3は1と等しくなりません。

私たちはどのように2/3を表しますか? .666666は少なくとも2 * 1/3 = 2/3を保証します。しかし2/3 + 1/3は1と等しくなりません。

.666667の2/3を表すことができます。しかし2 * 1/32/3と等しくありません。しかし、少なくとも1/3 + 2/3は1に等しくなります。

したがって、おおよその表現では、正確な正解を保証することはできず、十分な解答のみを閉じることが重要です。一般的に、あなたが何をしているのか、理由を理解していない限り、浮動小数点数を平等に比較することは絶対に避けてください。

0

Cに関して最初に知っておかなければならないことは、コンパイラによる浮動小数点数の実装のために2つの浮動小数点数が等しいかどうかをテストすることは非常に間違っているということです。 浮動小数点変数に格納する際に '1.3'を指定すると、コンパイラが格納する小数点以下の桁数をすべて詰め込んでいないため、いくつかの桁でいっぱいになるため、等価性のテストに失敗する可能性があります。

関連する問題