BigDecimal est égal à () par rapport à compareTo ()

158

Considérez la classe de test simple:

import java.math.BigDecimal;

/**
 * @author The Elite Gentleman
 *
 */
public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BigDecimal x = new BigDecimal("1");
        BigDecimal y = new BigDecimal("1.00");
        System.out.println(x.equals(y));
        System.out.println(x.compareTo(y) == 0 ? "true": "false");
    }

}

Vous pouvez (consciemment) dire que xc'est égal à y(pas une référence d'objet), mais lorsque vous exécutez le programme, le résultat suivant s'affiche:

false
true

Question: Quelle est la différence entre compareTo()et equals()dans BigDecimalqui compareTopeut déterminer qui xest égal à y?

PS: Je vois que BigDecimal a une inflate()méthode sur la equals()méthode. Que fait inflate()-il réellement?

Buhake Sindi
la source
1
Annonce inflate(): elle ne fait pas partie de l'API publique car elle ne manipule que la représentation interne et n'a aucun effet visible vers "l'extérieur". Donc, à moins que vous ne souhaitiez vraiment étudier la mise BigDecimalen œuvre en profondeur, je vous suggère d'ignorer cette méthode.
Joachim Sauer
Une brève explication et des extraits de code source peuvent être trouvés ici
xenteros

Réponses:

225

La réponse se trouve dans le JavaDoc de la equals()méthode :

À la différence compareTo, cette méthode considère deux BigDecimalobjets égaux uniquement s'ils sont égaux en valeur et en échelle (donc 2,0 n'est pas égal à 2,00 par rapport à cette méthode).

En d'autres termes: equals()vérifie si les BigDecimalobjets sont exactement les mêmes dans tous les aspects. compareTo()"seulement" compare leur valeur numérique.

Quant à savoir pourquoi equals() se comporte de cette façon, cela a été répondu dans cette question SO .

Joachim Sauer
la source
24
C'est une partie très délicate BigDecimalsi vous ne lisez pas attentivement le JavaDoc. :) - Nous avons eu quelques bugs étranges jusqu'à ce que nous réalisions la différence.
Thomas
3
De nombreuses parties de l'API standard agissent "de manière non intuitive", alors que la chose intuitive ne serait pas correcte. BigDecimalest une telle chose. Par conséquent, il faut toujours vérifier le JavaDoc. Au moins une fois, vous découvrez que quelque chose d'étrange se passe.
Joachim Sauer
7
Drôle. Après avoir lu votre réponse, je viens de vérifier Comparable et il indique que la cohérence avec des égaux "est fortement recommandée (mais pas obligatoire)"
SJuan76
4
J'ai demandé pourquoi: stackoverflow.com/questions/14102083/…
bacar
8
@StephenC Je pense qu'il est incorrect que cette incohérence existe.
Matt R du
1

Je vois que BigDecimal a une méthode inflate () sur la méthode equals (). Que fait réellement inflate ()?

Fondamentalement, inflate()appelle BigInteger.valueOf(intCompact)si nécessaire, c'est-à-dire qu'il crée la valeur non mise à l'échelle qui est stockée en tant que BigIntegerfrom long intCompact. Si vous n'en avez pas besoin BigIntegeret que la valeur non mise à l'échelle s'insère dans un long BigDecimalsemble essayer d'économiser de l'espace le plus longtemps possible.

Thomas
la source
Je n'ai aucune idée de ce que vous avez écrit (surtout avec la dernière phrase).
Buhake Sindi
@The Elite Gentlement La dernière phrase devrait simplement dire que BigDecimalconserve en interne sa valeur non mise à l'échelle dans a longainsi que dans a BigInteger. Si le BigIntegern'est pas nécessaire en interne, il n'est pas créé mais s'il est nécessaire (par exemple, quand il equalsrencontre un gonflé et un gonflé gonflé BigDecimal) () `est utilisé pour le créer. - Pour résumer: inflate()gère les conversions internes si nécessaire et depuis est privé, cela ne devrait pas avoir d'importance pour les utilisateurs de la classe.
Thomas
1

Je crois que la bonne réponse serait de faire en sorte que les deux nombres (BigDecimals) aient la même échelle, alors nous pourrons décider de leur égalité. Par exemple, ces deux nombres sont-ils égaux?

1.00001 and 1.00002

Eh bien, cela dépend de l'échelle. Sur l'échelle 5 (5 décimales), non, ce ne sont pas les mêmes. mais sur des précisions décimales plus petites (échelle 4 et inférieure), ils sont considérés comme égaux. Je suggère donc de rendre l'échelle des deux nombres égale, puis de les comparer.

Monsieur Q
la source
-10

Vous pouvez également comparer avec une valeur double

BigDecimal a= new BigDecimal("1.1"); BigDecimal b =new BigDecimal("1.1");
System.out.println(a.doubleValue()==b.doubleValue());
Rashmi singh
la source
5
Veuillez éviter cette solution autant que possible. Même les doubles doivent être comparés à "epsilon". Il n'y a aucun sens à avoir BigDecimal et à le comparer comme des doubles. Il y a de très fortes chances que vous tiriez votre propre jambe.
Vadim Kirilchuk
Les valeurs doubles doivent être comparées à l'aide d'epsillons
Bishwajit Purkaystha