次のコードが生成されると思っていました: " Both are equal
" ですが、" Both are NOT equal
" になりました:
float a=1.3f;
double b=1.3;
if(a==b)
{
System.out.println("Both are equal");
}
else{
System.out.println("Both are NOT equal");
}
これの理由は何ですか?
次のコードが生成されると思っていました: " Both are equal
" ですが、" Both are NOT equal
" になりました:
float a=1.3f;
double b=1.3;
if(a==b)
{
System.out.println("Both are equal");
}
else{
System.out.println("Both are NOT equal");
}
これの理由は何ですか?
これは、1.3 に最も近い float 値が 1.3 に最も近い double 値と同じではないためです。どちらの値も正確に1.3 にはなりません。これは、繰り返し発生しないバイナリ表現では正確に表すことができません。
これが発生する理由を別の方法で理解するために、2 つの10 進浮動小数点型 (decimal5
と) があるとdecimal10
します。ここで、数値は有効桁数を表します。ここで、「3 分の 1」の値を両方に割り当てようとしたとします。あなたはで終わるだろう
decimal5 oneThird = 0.33333
decimal10 oneThird = 0.3333333333
明らかに、これらの値は等しくありません。ここでは、ベースが異なるだけで、まったく同じことです。
ただし、値を精度の低い型に制限すると、この特定のケースでは値が等しいことがわかります。
double d = 1.3d;
float f = 1.3f;
System.out.println((float) d == f); // Prints true
ただし、そうであるとは限りません。10 進数リテラルから double 表現への近似、およびその値の float 表現への近似は、単純な 10 進数から float への近似よりも精度が低くなることがあります。この 1.0000001788139343 の一例 (この例を見つけてくれた stephentyrone に感謝)。
もう少し安全に、double 間の比較を行うことができますがfloat
、元の割り当てでリテラルを使用します。
double d = 1.3f;
float f = 1.3f;
System.out.println(d == f); // Prints true
後者の場合、次のように言います。
decimal10 oneThird = 0.3333300000
ただし、コメントで指摘されているように、浮動小数点値を == と比較するべきではありません。まさにこの種のことのために、それが正しいことであるということはほとんどありません。通常、2 つの値を比較したい場合は、ある種の「ファジー」等値比較を行い、2 つの数値が目的に「十分に近い」かどうかを確認します。詳細については、Java トラップ: ダブルページを参照してください。
絶対的な等価性を本当にチェックする必要がある場合は、通常、最初に別の数値形式を使用する必要があることを示しています。たとえば、財務データの場合、おそらくBigDecimal
.
float は、単精度の浮動小数点数です。double は倍精度浮動小数点数です。詳細はこちら: http://www.concentric.net/~Ttwang/tech/javafloat.htm
注:浮動小数点数が正確に等しいかどうかをチェックするのはお勧めできません。ほとんどの場合、デルタ値または許容値に基づいて比較を行う必要があります。
例えば:
float a = 1.3f;
double b = 1.3;
float delta = 0.000001f;
if (Math.abs(a - b) < delta)
{
System.out.println("Close enough!");
}
else
{
System.out.println("Not very close!");
}
一部の数値は浮動小数点で正確に表すことができない0.01
ため (例: )、等しいかどうかを比較すると予期しない結果が生じる場合があります。
浮動小数点数が等しいかどうかをチェックしないでください。具体的には、あなたの質問に答えるために、数値 1.3 はバイナリ浮動小数点として表すのが難しく、double と float の表現は異なります。
この記事を読んでください。
上記の記事では、double 型と float 型を使用している場合のシナリオの例を明確に示しています。
float a=1.3f;
double b=1.3;
この時点で、実数 1.3 の 2 進近似を含む 2 つの変数があります。最初の概算は約 7 桁の精度で、2 番目の概算は約 15 桁の精度です。
if(a==b) {
式a==b
は 2 段階で評価されます。最初に、バイナリ表現をパディングすることによって、 の値が a から aにa
変換されます。結果は、Real 1.3 の表現として約 7 桁までしか正確ではありません。次に、2 つの異なる近似を比較します。それらは異なるため、 の結果はです。float
double
a==b
false
学ぶべき教訓は 2 つあります。
浮動小数点 (および倍精度) リテラルは、ほとんどの場合近似値です。たとえば、リテラルに対応する実際の数1.3f
は、実数と正確には等しくありません1.3
。
浮動小数点計算を行うたびに、エラーが忍び寄ります。これらのエラーは蓄積する傾向があります。したがって、浮動小数点数と倍精度数を比較する場合、通常、単純な「==」、「<」などを使用するのは間違いです。代わりに、適切に選択され|a - b| < delta
た whereを使用する必要がありdelta
ます。(また、何が適切かを判断することも、delta
必ずしも簡単ではありません。)
数値解析でそのコースを受講する必要がありました:-)
実際には float も double も 1.3 を格納できません。冗談ではありません。このビデオを注意深く見てください。
https://www.youtube.com/watch?v=RtHKwsXuRkk&index=50&list=PL6pxHmHF3F5JPdnEqKALRMgogwYc2szp1