double値をゼロと比較するときは注意する必要がありますか?
if ( someAmount <= 0){
.....
}
本当に注意したい場合は、次のようなものでゼロのイプシロン内にあるかどうかをテストできます
double epsilon = 0.0000001;
if ( f <= ( 0 - epsilon ) ) { .. }
else if ( f >= ( 0 + epsilon ) ) { .. }
else { /* f "equals" zero */ }
または、倍精度浮動小数点数を分岐する前に、指定された精度に単純に丸めることができます。
浮動小数点数の誤差の比較に関する興味深い詳細については、Bruce Dawson による記事を参照してください。
等しい場合: (つまり==
、または!=
) はい。
他の比較演算子 ( <
、>
、<=
、 ) については、エッジ ケースについて考えている>=
かどうかによって異なります。エッジケースを気にしない場合、通常は問題ありませんが、入力数値がどこから来て、どのように使用されるかによって異なります。<
<=
(3.0/10.0) <= 0.3
として評価されることを期待してtrue
いる場合 (浮動小数点エラーによって 3.0/10.0 が 0.300000000001 のように 0.3 よりわずかに大きい数値に評価される場合はそうではない可能性があります)、次のように評価される場合、プログラムの動作は悪くなりますfalse
。注意が必要です。
優れた数値アルゴリズムは、等値やエッジ ケースに依存することはほとんどありません。0 から 1 の間の任意の数値である入力として ' x
' を受け取るアルゴリズムがある場合、一般に か かどうかは問題ではありませ0 < x < 1
ん0 <= x <= 1
。ただし、例外もあります。分岐点や特異点を持つ関数を評価するときは注意が必要です。
中間量がy
あり、 を期待しy >= 0
、 を評価sqrt(y)
する場合、浮動小数点エラーによって y が非常に小さい負の数になり、sqrt()
関数がエラーをスローしないことを確認する必要があります。sqrt(max(y,0))
(これは複素数が関係していない状況であると仮定します。)数値エラーについて確信が持てない場合は、代わりに評価するでしょう。
1/y
orのような式の場合log(y)
、実用的な意味では、y がゼロ (この場合、特異点エラーが発生します) であるか、y がゼロに非常に近い数値であるか (この場合、非常に大きな数値が得られます) は問題ではありません。その大きさは y の値に非常に敏感です) -- どちらの場合も数値的な観点からは「悪い」ので、何をしようとしているのか、y
値がゼロ付近。
計算方法によってsomeAmount
は、float/doublesで奇妙な動作が予想される場合があります
基本的に、float / doublesを使用して数値データを2進表現に変換すると、エラーが発生しやすくなります。これは、一部の数値をカマキリ/指数で表すことができないためです。
これに関するいくつかの詳細については、この小さな記事を読むことができます
特に通貨と税の計算には、java.lang.Math.signum
またはの使用を検討する必要がありますjava.math.BigDecimal
自動ボックス化解除に注意してください。
Double someAmount = null;
if ( someAmount <= 0){
ブーム、NullPointerException。
はい、気をつけてください。
提案: 良い方法の 1 つは、BigDecimal
等しいかどうかを 0 にチェックするために使用することです。
BigDecimal balance = pojo.getBalance();//get your BigDecimal obj
0 != balance.compareTo(BigDecimal.ZERO)
説明 :
関数はこれを指定されたcompareTo()
と比較します。値は等しいがスケールが異なる (2.0 と 2.00 など) 2 つのオブジェクトは、この方法では等しいと見なされます。このメソッドは、6 つの比較演算子ごとに個別のメソッドに優先して提供されます。これらの比較を実行するための推奨イディオムは次のとおりです。BigDecimal
BigDecimal
BigDecimal
boolean
(<, ==, >, >=, !=, <=)
(x.compareTo(y) <op> 0)
(SonarQube のドキュメントに感謝します)
浮動小数点演算は、そのような値をバイナリ表現で格納するという課題があるため、正確ではありません。さらに悪いことに、浮動小数点演算は連想的ではありません。float または double を一連の単純な数学演算にプッシュすると、各ステップで丸めが行われるため、これらの演算の順序に基づいて答えが異なります。
単純な浮動小数点代入でさえ単純ではありません。
float f = 0.1; // 0.100000001490116119384765625
double d = 0.1; // 0.1000000000000000055511151231257827021181583404541015625
(結果は、コンパイラとコンパイラの設定によって異なります);
したがって、float 値または double 値で等値 (==) および不等値 (!=) 演算子を使用すると、ほとんどの場合エラーになります。代わりに、最善の方法は、浮動小数点比較を完全に避けることです。それが不可能な場合は、浮動小数点比較を適切に処理できる BigDecimal など、Java の浮動小数点数を処理する Number の使用を検討する必要があります。3 番目のオプションは、等しいかどうかではなく、値が十分に近いかどうかを調べることです。つまり、保存された値と期待値の差の絶対値を、許容誤差の範囲と比較します。これはすべてのケース (NaN や Infinity など) をカバーしていないことに注意してください。
エッジケースを気にしない場合は、テストしてsomeAmount <= 0
ください。コードの意図が明確になります。気にするなら、それは計算方法someAmount
と、不等式をテストする理由によって異なります。
double または float 値が 0 であることを確認します。値が 0 に近いかどうかを検出するためにエラーしきい値が使用されますが、完全には 0 ではありません。
doubleがゼロかどうかをテストする方法は? @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 です。
楽しんで @。@