197 votes

BigDecimal equals() versus compareTo()

Considérons 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 x est égal à y (pas de référence objet), mais lorsque vous exécutez le programme, le résultat suivant apparaît :

false
true

Question : Quelle est la différence entre compareTo() y equals() en BigDecimal que compareTo peut déterminer que x est égal à y ?

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

1 votes

Ad inflate() il ne fait pas partie de l'API publique car il ne manipule que la représentation interne et n'a pas d'effet visible pour l'"extérieur". Donc, à moins que vous ne souhaitiez vraiment étudier l'implémentation de la fonction BigDecimal en profondeur, je vous suggère d'ignorer cette méthode.

0 votes

Une brève explication et des extraits du code source peuvent être trouvés aquí

278voto

Joachim Sauer Points 133411

La réponse est dans la JavaDoc de la equals() méthode :

Contrairement à compareTo cette méthode considère deux BigDecimal Les objets ne sont égaux que s'ils sont égaux en valeur et en échelle (ainsi 2,0 n'est pas égal à 2,00 lorsqu'il est comparé par cette méthode).

En d'autres termes : equals() vérifie si le BigDecimal les objets sont exactement la même chose en chaque aspect. compareTo() "seulement" compare leur valeur numérique.

Quant à pourquoi equals() se comporte de cette manière, il a été répondu à cette question dans cette question SO .

31 votes

C'est une partie très délicate de BigDecimal si vous ne lisez pas attentivement la JavaDoc. :) - Nous avons eu quelques bogues étranges à cause de cela jusqu'à ce que nous réalisions la différence.

3 votes

De nombreuses parties de l'API standard agissent de manière "non intuitive", alors que la chose intuitive ne serait pas correcte. BigDecimal est l'une de ces choses. Il faut donc toujours vérifier la JavaDoc. Au moins une fois que vous aurez découvert que quelque chose d'étrange se passe.

7 votes

C'est drôle. Après avoir lu votre réponse, je viens de consulter Comparable et il indique que la cohérence avec les égaux "est fortement recommandée (mais pas obligatoire)".

2voto

Thomas Points 35713

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

En gros, inflate() appelle BigInteger.valueOf(intCompact) si nécessaire, c'est-à-dire qu'il crée la valeur non échelonnée qui est stockée en tant que BigInteger de long intCompact . Si vous n'avez pas besoin de ça BigInteger et la valeur non échelonnée s'inscrit dans un long BigDecimal semble essayer d'économiser de l'espace aussi longtemps que possible.

0 votes

Je n'ai aucune idée de ce que vous avez écrit (surtout avec la dernière phrase).

0 votes

@The Elite Gentlement La dernière phrase devrait juste dire qu'en interne. BigDecimal conserve sa valeur non échelonnée dans un long ainsi qu'un BigInteger . Si le BigInteger n'est pas nécessaire en interne, il n'est pas créé mais s'il est nécessaire (par exemple lorsque equals rencontre un gonflé et un non gonflé BigDecimal) inflate()` est utilisé pour le créer. - Pour résumer : inflate() gère les conversions internes si nécessaire et, étant donné qu'elle est privée, cela ne devrait pas avoir d'importance pour les utilisateurs de la classe.

2voto

user3593084 Points 42

Je pense que la bonne réponse serait de faire en sorte que les deux nombres (BigDecimals), aient la même échelle, puis 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, ils 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 et de les comparer ensuite.

-15voto

Rashmi singh Points 101

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X