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?

JoJo
quelle
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
Böhmisch
quelle
BigDecimal.ZERO.compareTo (Preis) == 0
Jackkobec
97

Alternativ kann signum () verwendet werden:

if (price.signum() == 0) {
    return true;
}
kman
quelle
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
Pablochan
quelle
3
Erlaubnis, Ihre Terminologie einer angeforderten "Yoda-Bedingung" zu stehlen.
SimplyPanda
3
Das ist fantastisch .
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) { ... }
gpol
quelle
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.

Edwin Dalorzo
quelle
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().

NominSim
quelle
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
Tihamer
quelle
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
Nokuap
quelle
-2
BigDecimal.ZERO.setScale(2).equals(new BigDecimal("0.00"));
DongHoon Kim
quelle
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
-8

Es gibt eine statische Konstante, die 0 darstellt :

BigDecimal.ZERO.equals(selectPrice)

Sie sollten dies tun anstatt:

selectPrice.equals(BigDecimal.ZERO)

um den Fall zu vermeiden, wo selectPrice ist null.

tskuzzy
quelle
3
Java BigDecimals Verhalten von equalsund compareToist nicht so, wie Sie denken. docs.oracle.com/javase/1.5.0/docs/api/java/math/…
nhahtdh
Also für die zweite Zeile ... wenn selectedPrice null ist, wird einfach NullPointerException ausgelöst.
user3206236