Как сравнить два больших десятичных - PullRequest
0 голосов
/ 26 мая 2018

У меня следующий код, однако я не могу понять, почему два больших десятичных числа не считаются равными

class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        BigDecimal b = new BigDecimal(13.90);
        BigDecimal b2 = new BigDecimal("13.9");
        System.out.println(b.compareTo(b2));
    }
}

Этот код выводит 1 в качестве вывода.Почему это так?Разве это не должно быть 0?

Кроме того, если я пишу 13,9 вместо "13,9", это дает 0 в качестве вывода

Ответы [ 3 ]

0 голосов
/ 26 мая 2018

Числовые значения с плавающей точкой не точны, они приблизительны.Поэтому, когда вы вводите литеральное значение 13,90, фактическое значение остается не совсем 13,90, а как можно ближе к нему.

Значения BigDecimal являются точными, а строки - просто строками.

Поэтому, когда вы используете новый BigDecimal (13.90) и новый BigDecimal ("13.9"), первый содержит значение, которое является точно переданным ему значением с плавающей точкой, которое очень близко, но отличается от 13.9.А второй содержит ровно 13,9.

Один из них - 13,9, а другой близок, но не равен 13,9.Таким образом, два объекта не равны.

0 голосов
/ 26 мая 2018

javadoc для конструктора BigDecimal двойных примечаний, что результат "может быть несколько непредсказуемым" .Это потому, что входное десятичное значение на самом деле является приближением с плавающей запятой.Обычно рекомендуется создавать десятичные значения с помощью конструктора BigDecimal String.Однако, если вы этого не делаете или не можете сделать, вы всегда можете установить масштаб и круг.Код ниже даст вам результаты, которые вы ищете.

BigDecimal b = new BigDecimal(13.90).setScale(2,BigDecimal.ROUND_HALF_UP);
BigDecimal b2 = new BigDecimal("13.9");
System.out.println(b.compareTo(b2));

Примечание: округление происходит в конце шкалы.Таким образом, с набором 2 значение 13,900004 округляется до 13,90.

0 голосов
/ 26 мая 2018

Потому что вы предполагаете, что если вы используете 13,9, это будет точно 13,9.Попробуйте напечатать значения b и b2, и вы увидите, что 13.9 на самом деле 13.9000000000000003552713678800500929355621337890625, а значение проанализированной строки - 13,9.Так что b (немного) выше, чем b2.

public static void main(String...strings) {
            BigDecimal b = new BigDecimal(13.9);
            BigDecimal b2 = new BigDecimal("13.9");
            System.out.printf("%s %s %d%n", b, b2, b.compareTo(b2));
}

Дает в качестве вывода:

13.9000000000000003552713678800500929355621337890625 13.9 1

По теме математики с плавающей запятой вы можете прочитать Почему числа с плавающей точкой неточны? и другие ссылки доступны в stackoverflow.

...