Comment vérifier si la variable BigDecimal == 0 en Java?


202

J'ai le code suivant en Java;

BigDecimal price; // assigned elsewhere

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

Quelle est la meilleure façon d'écrire la condition if?


12
De nombreuses réponses suggèrent d'utiliser la méthode .equals () de BigDecimal. Mais cette méthode prend en compte l'échelle, elle n'est donc pas équivalente à l'utilisation de compareTo ().
GriffeyDog

Réponses:


474

Utilisez compareTo(BigDecimal.ZERO)au lieu de equals():

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

La comparaison avec la BigDecimalconstante BigDecimal.ZEROévite d'avoir à construire new BigDecimal(0)chaque exécution.

FYI, a BigDecimalégalement des constantes BigDecimal.ONEet BigDecimal.TENpour votre commodité.


Remarque!

La raison pour laquelle vous ne pouvez pas l'utiliser BigDecimal#equals()est qu'elle prend en compte l' échelle :

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

il ne convient donc pas pour une comparaison purement numérique. Cependant, BigDecimal.compareTo()ne tient pas compte de l'échelle lors de la comparaison:

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

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

97

Alternativement, signum () peut être utilisé:

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

21
C'est peut-être plus rapide, mais compareTo (BigDecimal.ZERO) est plus lisible.
ElYeante

@ElYeante, vous pouvez toujours envelopper cela avec une méthode, qui a un nom plus lisible, ou même décrit une partie de votre logique métier, connectée avec une telle comparaison
WeGa

3
Malheureusement, signum () n'est pas à sécurité nulle, alors que compareTo l'est, lors de la comparaison comme BigDecimal.ZERO.compareTo (), alors faites attention à cela
WeGa

15
@WeGa Ce n'est pas vrai: BigDecimal.ZERO.compareTo(null)lancera NPE
ACV le

5
@ACV, merci pour votre vigilance. En regardant le code source, compareTo () n'attend en effet que des arguments non nuls.
WeGa


5

J'utilise généralement les éléments suivants:

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

5

Alternativement, je pense qu'il convient de mentionner que le comportement des méthodes equals et compareTo dans la classe BigDecimal ne sont pas cohérents .

Cela signifie essentiellement que:

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

Par conséquent, vous devez être très prudent avec l'échelle de votre someValuevariable, sinon vous obtiendriez un résultat inattendu.


5

Vous voudriez utiliser equals () car ce sont des objets, et utiliser l'instance ZERO intégrée:

if(selectPrice.equals(BigDecimal.ZERO))

Notez que .equals()prend en compte l'échelle, donc à moins que selectPrice n'ait la même échelle (0) que .ZEROcela retournera false.

Pour prendre l'échelle de l'équation pour ainsi dire:

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

Je dois noter que pour certaines situations mathématiques, 0.00 != 0c'est pourquoi j'imagine .equals()tenir compte de l'échelle. 0.00donne une précision à la centième place, alors qu'il 0n'est pas si précis. Selon la situation avec laquelle vous voudrez peut-être rester .equals().


Le comportement de Java BigDecimal equalset compareTon'est pas comme vous le pensez. docs.oracle.com/javase/1.5.0/docs/api/java/math/…
nhahtdh

Voulez-vous expliquer ce que vous voulez dire au lieu de créer un lien vers les documents? Ce que j'ai suggéré devrait fonctionner pour le PO.
NominSim

La réponse d'Edwin Dalorzo l'explique assez bien, en fait. equalsprend en compte l'échelle, ce qui n'est pas ce que nous voulons ici.
nhahtdh

@nhahtdh Merci pour l'information, en fait bien qu'il y ait des situations où equals devrait être utilisé à la place de compareTo(). L'OP ne spécifie pas quel type de mathématiques il utilise, vous avez donc raison, il vaut mieux lui donner les deux options.
NominSim

3

GriffeyDog est définitivement correct:

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)));

Résultats:

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

Bien que je comprenne les avantages de la comparaison BigDecimal, je ne la considérerais pas comme une construction intuitive (comme le sont les opérateurs ==, <,>, <=,> =). Lorsque vous tenez un million de choses (ok, sept choses) dans votre tête, alors tout ce que vous pouvez réduire votre charge cognitive est une bonne chose. J'ai donc construit quelques fonctions pratiques utiles:

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);
}

Voici comment les utiliser:

    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));

Les résultats ressemblent à ceci:

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
Il y a plusieurs réponses expliquant exactement cela. Quel est l'intérêt d'ajouter une autre réponse? Si vous avez des informations supplémentaires, c'est une bonne idée d'ajouter une nouvelle réponse, mais ce n'est pas le cas dans ce post.
Tom

Point pris. Cependant, lorsque j'apprends quelque chose, j'aime voir autant d'exemples que possible, même s'ils sont similaires. Pour toi, Tom, j'ai ajouté ma bibliothèque que j'ai trouvée utile. Votre kilométrage peut varier. :-)
Tihamer

0

Je veux juste partager ici quelques extensions utiles pour kotlin

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
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant la manière et / ou la raison pour laquelle il résout le problème améliorerait la valeur à long terme de la réponse. N'oubliez pas que vous répondrez à la question des lecteurs à l'avenir, pas seulement à la personne qui pose la question maintenant! Veuillez modifier votre réponse pour ajouter une explication et donner une indication des limitations et hypothèses applicables. Cela ne fait pas de mal non plus de mentionner pourquoi cette réponse est plus appropriée que d'autres.
Dev-iL

-8

Il existe une constante statique qui représente 0 :

BigDecimal.ZERO.equals(selectPrice)

Vous devriez faire ceci au lieu de:

selectPrice.equals(BigDecimal.ZERO)

afin d'éviter le cas où selectPriceest null.


3
Le comportement de Java BigDecimal equalset compareTon'est pas comme vous le pensez. docs.oracle.com/javase/1.5.0/docs/api/java/math/…
nhahtdh

donc pour la deuxième ligne ... si selectedPrice est null alors il lèvera simplement NullPointerException.
user3206236
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.