Wie überprüfe ich, ob die BigDecimal-Variable == 0 in Java ist?


202

Ich habe den folgenden Code in Java;

BigDecimal price; // assigned elsewhere

if (price.compareTo(new BigDecimal("0.00")) == 0) {
    return true;
}

Was ist der beste Weg, um die if-Bedingung zu schreiben?


12
Viele Antworten schlagen vor, die .equals () -Methode von BigDecimal zu verwenden. Diese Methode berücksichtigt jedoch die Skalierung und ist daher nicht gleichbedeutend mit der Verwendung von compareTo ().
GriffeyDog

Antworten:


471

Verwenden Sie compareTo(BigDecimal.ZERO)anstelle von equals():

if (price.compareTo(BigDecimal.ZERO) == 0) // see below

Durch den Vergleich mit der BigDecimalKonstante wird BigDecimal.ZEROvermieden, dass a konstruiert werden mussnew BigDecimal(0) jeder Ausführung.

Zu Ihrer Information, BigDecimalhat auch Konstanten BigDecimal.ONEundBigDecimal.TEN Ihrer für Ihre Bequemlichkeit.


Hinweis!

Der Grund, den Sie nicht verwenden können, BigDecimal#equals()ist, dass die Skalierung berücksichtigt wird:

new BigDecimal("0").equals(BigDecimal.ZERO) // true
new BigDecimal("0.00").equals(BigDecimal.ZERO) // false!

Daher ist es für einen rein numerischen Vergleich ungeeignet. Allerdings BigDecimal.compareTo()ist nicht der Maßstab beim Vergleich:

new BigDecimal("0").compareTo(BigDecimal.ZERO) == 0 // true
new BigDecimal("0.00").compareTo(BigDecimal.ZERO) == 0 // true

BigDecimal.ZERO.compareTo (Preis) == 0
Jackkobec

97

Alternativ kann signum () verwendet werden:

if (price.signum() == 0) {
    return true;
}

21
Vielleicht ist es schneller, aber compareTo (BigDecimal.ZERO) ist besser lesbar.
ElYeante

@ ElYeante, Sie können dies immer mit einer Methode umschließen, die einen besser lesbaren Namen hat oder sogar einen Teil Ihrer Geschäftslogik beschreibt, die mit einem solchen Vergleich verbunden ist
WeGa

3
Leider ist signum () nicht null-sicher, wohingegen compareTo beim Vergleich wie BigDecimal.ZERO.compareTo () darauf achtet
WeGa

15
@WeGa Das ist nicht wahr: BigDecimal.ZERO.compareTo(null)wird NPE
ACV

5
@ACV, danke für deine Wachsamkeit. Im Quellcode erwartet compareTo () tatsächlich nur ein Argument ungleich Null.
WeGa

24

Es gibt eine Konstante, gegen die Sie prüfen können:

someBigDecimal.compareTo(BigDecimal.ZERO) == 0

3
Erlaubnis, Ihre Terminologie einer angeforderten "Yoda-Bedingung" zu stehlen.
SimplyPanda


Java BigDecimals Verhalten von equalsund compareToist nicht so, wie Sie denken. docs.oracle.com/javase/1.5.0/docs/api/java/math/…
nhahtdh

2
BigDecimals compareTo löst immer noch eine Ausnahme aus, wenn Sie eine Null übergeben.
John Jiang

5

Ich benutze normalerweise Folgendes:

if (selectPrice.compareTo(BigDecimal.ZERO) == 0) { ... }

5

Alternativ halte ich es für erwähnenswert, dass das Verhalten von equals- und compareTo-Methoden in der Klasse BigDecimal nicht miteinander übereinstimmt .

Dies bedeutet im Grunde:

BigDecimal someValue = new BigDecimal("0.00");
System.out.println(someValue.compareTo(BigDecimal.ZERO)==0); //true
System.out.println(someValue.equals(BigDecimal.ZERO)); //false

Daher müssen Sie mit der Skalierung in Ihrer someValueVariablen sehr vorsichtig sein , da Sie sonst ein unerwartetes Ergebnis erhalten.


5

Sie möchten equals () verwenden, da es sich um Objekte handelt, und die integrierte ZERO-Instanz verwenden:

if(selectPrice.equals(BigDecimal.ZERO))

Beachten Sie, dass .equals()die Skalierung berücksichtigt wird, es sei denn, selectPrice hat dieselbe Skalierung (0) wie.ZERO diese hat, wird false zurückgegeben.

Um die Gleichung sozusagen aus der Gleichung herauszunehmen:

if(selectPrice.compareTo(BigDecimal.ZERO) == 0)

Ich sollte das für bestimmte mathematische Situationen beachten, 0.00 != 0weshalb ich mir vorstelle, .equals()die Skala zu berücksichtigen. 0.00gibt dem Hundertstel Platz Präzision, während 0es nicht so genau ist. Abhängig von der Situation möchten Sie vielleicht bleiben .equals().


Java BigDecimals Verhalten von equalsund compareToist nicht so, wie Sie denken. docs.oracle.com/javase/1.5.0/docs/api/java/math/…
nhahtdh

Möchten Sie erklären, was Sie meinen, anstatt auf die Dokumente zu verlinken? Was ich vorgeschlagen habe, sollte für das OP funktionieren.
NominSim

Die Antwort von Edwin Dalorzo erklärt es eigentlich ganz gut. equalsberücksichtigt die Skalierung, was wir hier nicht wollen.
nhahtdh

@nhahtdh Danke für die Information, in der Tat , obwohl es Situationen geben , wo equals sollte statt verwendet werden compareTo(). Das OP gibt nicht an, welche Art von Mathematik er verwendet. Sie haben also Recht, es ist besser, ihm beide Optionen zu geben.
NominSim

3

GriffeyDog ist definitiv richtig:

Code:

BigDecimal myBigDecimal = new BigDecimal("00000000.000000");
System.out.println("bestPriceBigDecimal=" + myBigDecimal);
System.out.println("BigDecimal.valueOf(0.000000)=" + BigDecimal.valueOf(0.000000));
System.out.println(" equals=" + myBigDecimal.equals(BigDecimal.ZERO));
System.out.println("compare=" + (0 == myBigDecimal.compareTo(BigDecimal.ZERO)));

Ergebnisse:

myBigDecimal=0.000000
BigDecimal.valueOf(0.000000)=0.0
 equals=false
compare=true

Obwohl ich die Vorteile des BigDecimal-Vergleichs verstehe, würde ich ihn nicht als intuitives Konstrukt betrachten (wie die Operatoren ==, <,>, <=,> =). Wenn Sie eine Million Dinge (ok, sieben Dinge) in Ihrem Kopf halten, ist alles, was Sie Ihre kognitive Belastung reduzieren können, eine gute Sache. Also habe ich einige nützliche Komfortfunktionen erstellt:

public static boolean equalsZero(BigDecimal x) {
    return (0 == x.compareTo(BigDecimal.ZERO));
}
public static boolean equals(BigDecimal x, BigDecimal y) {
    return (0 == x.compareTo(y));
}
public static boolean lessThan(BigDecimal x, BigDecimal y) {
    return (-1 == x.compareTo(y));
}
public static boolean lessThanOrEquals(BigDecimal x, BigDecimal y) {
    return (x.compareTo(y) <= 0);
}
public static boolean greaterThan(BigDecimal x, BigDecimal y) {
    return (1 == x.compareTo(y));
}
public static boolean greaterThanOrEquals(BigDecimal x, BigDecimal y) {
    return (x.compareTo(y) >= 0);
}

So verwenden Sie sie:

    System.out.println("Starting main Utils");
    BigDecimal bigDecimal0 = new BigDecimal(00000.00);
    BigDecimal bigDecimal2 = new BigDecimal(2);
    BigDecimal bigDecimal4 = new BigDecimal(4);  
    BigDecimal bigDecimal20 = new BigDecimal(2.000);
    System.out.println("Positive cases:");
    System.out.println("bigDecimal0=" + bigDecimal0 + " == zero is " + Utils.equalsZero(bigDecimal0));
    System.out.println("bigDecimal2=" + bigDecimal2 + " <  bigDecimal4=" + bigDecimal4 + " is " + Utils.lessThan(bigDecimal2, bigDecimal4));
    System.out.println("bigDecimal2=" + bigDecimal2 + " == bigDecimal20=" + bigDecimal20 + " is " + Utils.equals(bigDecimal2, bigDecimal20));
    System.out.println("bigDecimal2=" + bigDecimal2 + " <= bigDecimal20=" + bigDecimal20 + " is " + Utils.equals(bigDecimal2, bigDecimal20));
    System.out.println("bigDecimal2=" + bigDecimal2 + " <= bigDecimal4=" + bigDecimal4 + " is " + Utils.lessThanOrEquals(bigDecimal2, bigDecimal4));
    System.out.println("bigDecimal4=" + bigDecimal4 + " >  bigDecimal2=" + bigDecimal2 + " is " + Utils.greaterThan(bigDecimal4, bigDecimal2));
    System.out.println("bigDecimal4=" + bigDecimal4 + " >= bigDecimal2=" + bigDecimal2 + " is " + Utils.greaterThanOrEquals(bigDecimal4, bigDecimal2));
    System.out.println("bigDecimal2=" + bigDecimal2 + " >= bigDecimal20=" + bigDecimal20 + " is " + Utils.greaterThanOrEquals(bigDecimal2, bigDecimal20));
    System.out.println("Negative cases:");
    System.out.println("bigDecimal2=" + bigDecimal2 + " == zero is " + Utils.equalsZero(bigDecimal2));
    System.out.println("bigDecimal2=" + bigDecimal2 + " == bigDecimal4=" + bigDecimal4 + " is " + Utils.equals(bigDecimal2, bigDecimal4));
    System.out.println("bigDecimal4=" + bigDecimal4 + " <  bigDecimal2=" + bigDecimal2 + " is " + Utils.lessThan(bigDecimal4, bigDecimal2));
    System.out.println("bigDecimal4=" + bigDecimal4 + " <= bigDecimal2=" + bigDecimal2 + " is " + Utils.lessThanOrEquals(bigDecimal4, bigDecimal2));
    System.out.println("bigDecimal2=" + bigDecimal2 + " >  bigDecimal4=" + bigDecimal4 + " is " + Utils.greaterThan(bigDecimal2, bigDecimal4));
    System.out.println("bigDecimal2=" + bigDecimal2 + " >= bigDecimal4=" + bigDecimal4 + " is " + Utils.greaterThanOrEquals(bigDecimal2, bigDecimal4));

Die Ergebnisse sehen folgendermaßen aus:

Positive cases:
bigDecimal0=0 == zero is true
bigDecimal2=2 <  bigDecimal4=4 is true
bigDecimal2=2 == bigDecimal20=2 is true
bigDecimal2=2 <= bigDecimal20=2 is true
bigDecimal2=2 <= bigDecimal4=4 is true
bigDecimal4=4 >  bigDecimal2=2 is true
bigDecimal4=4 >= bigDecimal2=2 is true
bigDecimal2=2 >= bigDecimal20=2 is true
Negative cases:
bigDecimal2=2 == zero is false
bigDecimal2=2 == bigDecimal4=4 is false
bigDecimal4=4 <  bigDecimal2=2 is false
bigDecimal4=4 <= bigDecimal2=2 is false
bigDecimal2=2 >  bigDecimal4=4 is false
bigDecimal2=2 >= bigDecimal4=4 is false

1
Es gibt mehrere Antworten, die genau das erklären. Was bringt es, eine weitere Antwort hinzuzufügen? Wenn Sie zusätzliche Informationen haben, ist es eine gute Idee, eine neue Antwort hinzuzufügen, aber dies ist in diesem Beitrag nicht der Fall.
Tom

Punkt genommen. Wenn ich jedoch etwas lerne, sehe ich gerne so viele Beispiele wie möglich, auch wenn sie ähnlich sind. Für dich, Tom, habe ich meine Bibliothek hinzugefügt, die ich nützlich fand. Ihr Kilometerstand kann variieren. :-)
Tihamer

0

Ich möchte hier nur einige hilfreiche Erweiterungen für Kotlin veröffentlichen

fun BigDecimal.isZero() = compareTo(BigDecimal.ZERO) == 0
fun BigDecimal.isOne() = compareTo(BigDecimal.ONE) == 0
fun BigDecimal.isTen() = compareTo(BigDecimal.TEN) == 0

-2
BigDecimal.ZERO.setScale(2).equals(new BigDecimal("0.00"));

1
Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und / oder warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern. Denken Sie daran, dass Sie in Zukunft die Frage für die Leser beantworten, nicht nur für die Person, die jetzt fragt! Bitte bearbeiten Sie Ihre Antwort, um eine Erklärung hinzuzufügen, und geben Sie an, welche Einschränkungen und Annahmen gelten. Es tut auch nicht weh zu erwähnen, warum diese Antwort angemessener ist als andere.
Dev-iL

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.