web-dev-qa-db-ja.com

Java:二重値比較

Double値をゼロと比較するときは注意が必要ですか?

if ( someAmount <= 0){
.....
}
22
ZiG

あなたが本当に注意したいなら、あなたはそれが次のようなものでゼロのあるイプシロン内にあるかどうかをテストすることができます

double epsilon = 0.0000001;
if      ( f <= ( 0 - epsilon ) ) { .. }
else if ( f >= ( 0 + epsilon ) ) { .. }
else { /* f "equals" zero */ }

または、単純に倍精度浮動小数点数を特定の精度に丸めてから、それらを分岐します。

浮動小数点数の誤差の比較に関する興味深い詳細については、 これはBruce Dawsonによる記事です です。

18
Crashworks

同等の場合:(_==_または_!=_)はい。

その他の比較演算子(_<_、_>_、_<=_、_>=_)の場合は、エッジのケースであるかどうかによって異なります。 _<_が_<=_と同等かどうか。 Edgeのケースを気にしないのであれば、通常は問題ありませんが、入力番号がどこから来たのか、どのように使用されているかによって異なります。

_(3.0/10.0) <= 0.3_がtrueとして評価されることを期待している場合(浮動小数点エラーが原因で3.0/10.0が0.300000000001のように0.3をわずかに超える数値に評価される場合はそうではない)、falseとして評価されるとプログラムは正しく動作しません- -これはEdgeケースであり、注意する必要があります。

優れた数値アルゴリズムは、平等とエッジのケースにほとんど依存するべきではありません。 0から1までの任意の数値である 'x'を入力として受け取るアルゴリズムがある場合、通常、_0 < x < 1_と_0 <= x <= 1_のどちらでも問題ありません。ただし、例外があります。分岐点または特異点を持つ関数を評価するときは注意が必要です。

中間の量yがあり、_y >= 0_を期待していて、sqrt(y)を評価する場合、浮動小数点エラーによってyが非常に小さな負の数にならないことを確認する必要がありますエラーをスローするsqrt()関数。 (これが複素数が関係しない状況であると仮定します。)数値エラーがわからない場合は、代わりにsqrt(max(y,0))を評価します。

_1/y_またはlog(y)のような式の場合、実用的な意味では、yがゼロ(この場合、特異性エラーが発生します)であるか、またはyがゼロに非常に近い数値(どちらの場合も非常に大きな数が得られ、その大きさはyの値に非常に敏感です。どちらの場合も数値の観点からは「悪い」ので、私がやろうとしていることを再評価する必要があります、およびyの値がゼロに近い場合にどのような動作を探しているか。

9
Jason S

someAmountの計算方法によっては、float/doubleでの奇妙な動作が予想される場合があります

基本的に、一部の数値はMantis /指数で表現できないため、float/doubleを使用して数値データをバイナリ表現に変換するとエラーが発生しやすくなります。

これに関するいくつかの詳細については、以下を読むことができます この小さな記事

特に通貨と税金の計算では、Java.lang.Math.signumまたはJava.math.BigDecimalの使用を検討する必要があります

6
WiseTechi

自動開梱に注意する:

Double someAmount = null;
if ( someAmount <= 0){

ブーム、NullPointerException。

5
Thilo

はい、注意する必要があります。

提案:BigDecimalを使用して、等しいかどうかをチェックして0にするのが良い方法の1つです。

_BigDecimal balance = pojo.getBalance();//get your BigDecimal obj

0 != balance.compareTo(BigDecimal.ZERO)
_

説明 :

compareTo()関数は、このBigDecimalを指定されたBigDecimalと比較します。値は等しいがスケールが異なる(2.0と2.00など)2つのBigDecimalオブジェクトは、このメソッドによって等しいと見なされます。このメソッドは、6つのboolean比較演算子_(<, ==, >, >=, !=, <=)_の個々のメソッドに優先して提供されます。これらの比較を実行するための推奨イディオムは_(x.compareTo(y) <op> 0)_です。ここで、は6つの比較演算子の1つです。

(SonarQubeのドキュメントに感謝)

浮動小数点演算は、そのような値をバイナリ表現で格納するのが難しいため、不正確です。さらに悪いことに、浮動小数点演算は結合的ではありません。一連の単純な数学的演算でfloatまたはdoubleをプッシュすると、各ステップで丸めが行われるため、これらの演算の順序に基づいて答えが異なります。

単純な浮動小数点の割り当てでさえ簡単ではありません。

_float f = 0.1; // 0.100000001490116119384765625
double d = 0.1; // 0.1000000000000000055511151231257827021181583404541015625
_

(結果はコンパイラーとコンパイラーの設定によって異なります)。

したがって、floatまたはdouble値での等号(==)および不等号(!=)演算子の使用は、ほとんどの場合エラーになります。代わりに、最良の方法は、浮動小数点比較を完全に回避することです。それが不可能な場合は、浮動小数点比較を適切に処理できるBigDecimalなどのJavaの浮動小数点数の使用を検討する必要があります。 3番目のオプションは、等しいかどうかではなく、値が十分に近いかどうかを調べることです。つまり保存された値と期待値の差の絶対値を許容誤差のマージンと比較します。これはすべてのケースをカバーするわけではないことに注意してください(たとえば、NaNおよびInfinity)。

1
Vivek

Edgeのケースを気にしない場合は、someAmount <= 0。コードの意図が明確になります。気を付ければ、まあ... someAmountの計算方法と、不等式をテストする理由によって異なります。

0
quant_dev

Doubleまたはfloatの値が0であることを確認します。値が0に近いかどうかを検出するためにエラーしきい値が使用されますが、完全に0ではありません。この方法が私が出会ったものの中で最高だと思います。

ダブルがゼロかどうかをテストする方法 @William Morrisonが回答

public boolean isZero(double value, double threshold){
  return value >= -threshold && value <= threshold;
}

たとえば、しきい値を0に設定します。このように、

System.out.println(isZero(0.00, 0));
System.out.println(isZero(0, 0));
System.out.println(isZero(0.00001, 0));

上記の例のコードからのtrue、true、falseの結果。

楽しんで @。@

0
Luna Kong