BigDecimal дорівнює () проти порівняти до ()


157

Розглянемо простий тестовий клас:

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

}

Ви можете (свідомо) сказати, що xдорівнює y(не посилання на об'єкт), але при запуску програми відображається такий результат:

false
true

Питання: Яка різниця між compareTo()і equals()в BigDecimalчому compareToможна визначити, що xдорівнює y?

PS: Я бачу, що у BigDecimal є inflate()метод на equals()метод. Що насправді inflate()робить?


1
Оголошення inflate(): він не є частиною загальнодоступного API, оскільки він лише маніпулює внутрішнім представленням і не має видимого ефекту для "зовнішніх". Тому, якщо ви дійсно не хочете вивчити реалізацію BigDecimalпоглиблено, я пропоную вам проігнорувати цей метод.
Йоахім Зауер

Коротке пояснення та фрагменти вихідного коду можна знайти тут
xenteros

Відповіді:


224

Відповідь у JavaDoc equals()методу :

На відміну від compareToцього методу, два BigDecimalоб'єкти вважаються рівними лише в тому випадку, якщо вони є рівними за значенням і масштабом (таким чином, 2,0 не дорівнює 2,00 при порівнянні з цим методом).

Іншими словами: equals()чеки , якщо BigDecimalоб'єкти точно такий же в кожному аспекті. compareTo()"Тільки" порівнює їх числове значення.

Щодо того, чому так equals() поводиться, на це відповіли в цьому питанні .


24
Це дуже складна частина, BigDecimalякщо ви не читаєте уважно JavaDoc. :) - Ми отримали від цього деякі дивні помилки, поки не зрозуміли різницю.
Томас

3
Багато частин стандартного API діють "неінтуїтивно", коли інтуїтивно зрозуміла річ не була б правильною. BigDecimalє одна така річ. Тому завжди слід перевіряти JavaDoc. Принаймні раз, коли ви дізнаєтесь, що відбувається щось дивне.
Йоахім Зауер

7
Смішно. Прочитавши вашу відповідь, я щойно перевірив "Порівняно", і в ньому зазначається, що послідовність з рівними "настійно рекомендується (але не потрібно)"
SJuan76,

4
Я запитав , чому: stackoverflow.com/questions/14102083 / ...
Bacar

8
@StephenC Я вважаю, що це невідповідність існує неправильно .
Метт Р

1

Я бачу, що BigDecimal має метод надуття () за методом equals (). Що насправді робить inflate ()?

В основному, inflate()виклики BigInteger.valueOf(intCompact)при необхідності, тобто це створює немасштабне значення, яке зберігається як BigIntegerз long intCompact. Якщо вам це не потрібно, BigIntegerі нераспределенное значення вписується в, long BigDecimalздається, спробуйте максимально довго зберегти місце.


Я поняття не маю, що ви написали (особливо з останнім реченням).
Buhake Sindi

@ The Elite Gentlement Останнє речення повинно просто говорити про те, що внутрішньо BigDecimalзберігає нерозмірне значення як longв а, так і в BigInteger. Якщо BigIntegerне потрібно внутрішньо він не створений , але якщо це необхідно (наприклад , коли equalsзустрічає завищені і не-надутий BigDecimal) надути () `використовується для його створення - Підводячи підсумок :. inflate()Ручки внутрішні перетворення при необхідності і так як є приватним, це не має значення для користувачів класу
Thomas

1

Я вважаю, що правильною відповіддю було б зробити два числа (BigDecimals) однаковими масштабами, і тоді ми можемо прийняти рішення про їх рівність. Наприклад, чи рівні ці два числа?

1.00001 and 1.00002

Ну, це залежить від масштабу. У шкалі 5 (5 десяткових знаків) ні, вони не однакові. але на менших десяткових точності (шкала 4 і нижче) вони вважаються рівними. Тому пропоную зробити шкалу двох чисел рівними, а потім порівняти їх.


-10

Ви також можете порівняти з подвійним значенням

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

5
Будь ласка, уникайте цього рішення якомога більше. Навіть парні слід порівнювати з "епсілоном". Немає сенсу мати BigDecimal і порівнювати його як подвійне. Є дуже велика ймовірність, що ти будеш стріляти власною ногою.
Вадим Кирильчук

Подвійні значення необхідно порівнювати за допомогою епсіллонів
Bishwajit Purkaystha
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.