BigDecimal entspricht () versus compareTo ()


157

Betrachten Sie die einfache Testklasse:

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

}

Sie können (bewusst) sagen, dass dies xgleich ist y(keine Objektreferenz), aber wenn Sie das Programm ausführen, zeigt das folgende Ergebnis:

false
true

Frage: Was ist der Unterschied zwischen compareTo()und equals()in BigDecimaldem compareTokann feststellen , dass xgleich y?

PS: Ich sehe, dass BigDecimal eine inflate()Methode für eine equals()Methode hat. Was macht inflate()eigentlich?


1
Anzeige inflate(): Es ist nicht Teil der öffentlichen API, da es nur die interne Darstellung manipuliert und keine sichtbaren Auswirkungen nach außen hat. Wenn Sie sich also nicht BigDecimaleingehend mit der Implementierung von befassen möchten, empfehlen wir Ihnen, diese Methode zu ignorieren.
Joachim Sauer

Eine kurze Erklärung und Quellcode-Schnipsel finden Sie hier
Xenteros

Antworten:


224

Die Antwort befindet sich im JavaDoc der equals()Methode :

Im Gegensatz dazu compareTowerden bei dieser Methode zwei BigDecimalObjekte nur dann als gleich betrachtet, wenn sie in Wert und Skalierung gleich sind (daher ist 2,0 im Vergleich zu dieser Methode nicht gleich 2,00).

Mit anderen Worten: equals()Überprüft, ob die BigDecimalObjekte in jeder Hinsicht genau gleich sind . "nur" vergleicht ihren numerischen Wert.compareTo()

In Bezug auf , warum equals() diese Art und Weise verhält, dies beantwortet wurde in dieser Frage SO .


24
Das ist ein sehr schwieriger Teil, BigDecimalwenn Sie JavaDoc nicht sorgfältig lesen. :) - Wir haben einige seltsame Fehler, bis wir den Unterschied erkannten.
Thomas

3
Viele Teile der Standard-API verhalten sich "unintuitiv", wenn die intuitive Sache nicht korrekt wäre. BigDecimalist eine solche Sache. Daher sollte man immer das JavaDoc überprüfen. Zumindest wenn Sie herausfinden, dass etwas Seltsames passiert.
Joachim Sauer

7
Komisch. Nachdem ich Ihre Antwort gelesen habe, habe ich gerade Vergleichbar überprüft und festgestellt, dass die Übereinstimmung mit gleich "dringend empfohlen (aber nicht erforderlich)" ist
SJuan76

4
Ich habe gefragt, warum: stackoverflow.com/questions/14102083/…
Bacar

8
@ StephenC Ich denke, es ist falsch, dass diese Inkonsistenz besteht.
Matt R

1

Ich sehe, dass BigDecimal eine inflate () -Methode für die equals () -Methode hat. Was macht inflate () eigentlich?

Grundsätzlich inflate()Anrufe BigInteger.valueOf(intCompact)bei Bedarf, dh es den nicht skalierten Wert erzeugt, der als gespeichert BigIntegeraus long intCompact. Wenn Sie das nicht brauchen BigIntegerund der nicht skalierte Wert in a passt, long BigDecimalscheint er zu versuchen, so lange wie möglich Platz zu sparen.


Ich habe keine Ahnung, was Sie geschrieben haben (besonders mit dem letzten Satz).
Buhake Sindi

@ The Elite Gentlement Der letzte Satz sollte nur sagen, dass intern BigDecimalsein nicht skalierter Wert sowohl in a longals auch in a bleibt BigInteger. Wenn das BigIntegerintern nicht benötigt wird, wird es nicht erstellt, aber wenn es benötigt wird (z. B. wenn equalsein aufgeblasenes und ein nicht aufgeblasenes BigDecimal) Inflate () `zum Erstellen verwendet wird. - Um es zusammenzufassen: inflate()behandelt interne Konvertierungen, falls erforderlich und seitdem ist privat, es sollte für Benutzer der Klasse keine Rolle spielen.
Thomas

1

Ich glaube, dass die richtige Antwort darin besteht, die beiden Zahlen (BigDecimals) auf die gleiche Skala zu bringen, dann können wir über ihre Gleichheit entscheiden. Sind diese beiden Zahlen beispielsweise gleich?

1.00001 and 1.00002

Nun, es kommt auf die Skala an. Auf der Skala 5 (5 Dezimalstellen) sind sie nicht gleich. Bei kleineren Dezimalstellen (Skala 4 und niedriger) werden sie jedoch als gleich angesehen. Also schlage ich vor, die Skala der beiden Zahlen gleich zu machen und sie dann zu vergleichen.


-10

Sie können auch mit einem doppelten Wert vergleichen

BigDecimal a= new BigDecimal("1.1"); BigDecimal b =new BigDecimal("1.1");
System.out.println(a.doubleValue()==b.doubleValue());

5
Bitte vermeiden Sie diese Lösung so weit wie möglich. Sogar Doppel sollten mit "epsilon" verglichen werden. Es macht keinen Sinn, BigDecimal zu haben und es als Doppel zu vergleichen. Es besteht eine sehr hohe Wahrscheinlichkeit, dass Sie Ihr eigenes Bein schießen.
Vadim Kirilchuk

Doppelte Werte müssen mit Epsillons verglichen werden
Bishwajit Purkaystha
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.