BigDecimal равно () и сравнить с ()

158

Рассмотрим простой тестовый класс:

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

Ответы:

225

Ответ находится в JavaDoc equals()метода :

В отличие от compareToэтого, этот метод считает два BigDecimalобъекта равными, только если они равны по значению и масштабу (таким образом, 2,0 не равно 2,00 при сравнении этим методом).

Другими словами: equals()проверяет, являются ли BigDecimalобъекты абсолютно одинаковыми во всех аспектах. compareTo()«only» сравнивает их числовое значение.

Относительно того, почему equals() ведет себя так, на этот вопрос был дан ответ .

Йоахим Зауэр
источник
24
Это очень сложная часть, BigDecimalесли вы не будете внимательно читать JavaDoc. :) - Мы получили несколько странных ошибок, пока не поняли разницу.
Томас
3
Многие части стандартного API работают «не интуитивно», когда интуитивная вещь не будет правильной. BigDecimalодна такая вещь. Поэтому всегда следует проверять JavaDoc. По крайней мере, когда вы узнаете, что-то странное происходит.
Иоахим Зауэр
7
Веселая. После прочтения вашего ответа я только что проверил Comparable, и в нем говорится, что согласованность с «настоятельно рекомендуется (но не обязательна)»
SJuan76
4
Я спросил почему: stackoverflow.com/questions/14102083/…
bacar
8
@ StephhenC Я думаю, что это несоответствие существует неправильно .
Мэтт R
1

Я вижу, что BigDecimal имеет метод inflate () для метода equals (). Что на самом деле делает inflate ()?

По сути, inflate()вызывает BigInteger.valueOf(intCompact)при необходимости, то есть создает немасштабированное значение, которое сохраняется как BigIntegerот long intCompact. Если вам это не нужно, BigIntegerи немасштабированное значение вписывается в, long BigDecimalкажется, попытаться сэкономить место как можно дольше.

Томас
источник
Понятия не имею, что вы написали (особенно с последним предложением).
Бухаке Синди
@ The Elite Gentlement Последнее предложение должно просто сказать, что внутренне BigDecimalсохраняет его немасштабированное значение как в a, longтак и в a BigInteger. Если BigIntegerвнутренне не нужно, оно не создается, но если это необходимо (например, когда equalsвстречается надутый и не надутый BigDecimal) inflate () `, используется для его создания. - Подводя итог: inflate()обрабатывает внутренние преобразования, если необходимо, и так как является частным, это не должно иметь значения для пользователей класса
Томас
1

Я считаю, что правильным ответом было бы сделать так, чтобы два числа (BigDecimals) имели одинаковую шкалу, и тогда мы могли бы принять решение об их равенстве. Например, равны ли эти два числа?

1.00001 and 1.00002

Ну, это зависит от масштаба. По шкале 5 (5 знаков после запятой) нет, они не совпадают. но на меньшей десятичной точности (шкала 4 и ниже) они считаются равными. Поэтому я предлагаю сделать шкалу двух чисел равной, а затем сравнить их.

Mr.Q
источник
-10

Вы также можете сравнить с двойным значением

BigDecimal a= new BigDecimal("1.1"); BigDecimal b =new BigDecimal("1.1");
System.out.println(a.doubleValue()==b.doubleValue());
Рашми Сингх
источник
5
Пожалуйста, избегайте этого решения в максимально возможной степени. Даже двойники следует сравнивать с «эпсилоном». Нет смысла иметь BigDecimal и сравнивать его как удвоения ... очень высока вероятность того, что вы будете стрелять в собственную ногу.
Вадим Кирилчук
Значения Douuble должны сравниваться с использованием эпсилонов
Bishwajit Purkaystha