Как проверить, если переменная BigDecimal == 0 в Java?


202

У меня есть следующий код на Java;

BigDecimal price; // assigned elsewhere

if (price.compareTo(new BigDecimal("0.00")) == 0) {
    return true;
}

Как лучше написать условие if?


12
Многие ответы предлагают использовать метод BigDecimal .equals (). Но этот метод учитывает масштаб, поэтому не эквивалентен использованию compareTo ().
GriffeyDog

Ответы:


474

Используйте compareTo(BigDecimal.ZERO)вместо equals():

if (price.compareTo(BigDecimal.ZERO) == 0) // see below

Сравнение с BigDecimalконстантой BigDecimal.ZEROпозволяет избежать необходимости создавать new BigDecimal(0)каждое выполнение.

К вашему сведению, BigDecimalтакже есть константы BigDecimal.ONEи BigDecimal.TENдля вашего удобства.


Заметка!

Причина, по которой вы не можете использовать BigDecimal#equals()это то, что учитывает масштаб :

new BigDecimal("0").equals(BigDecimal.ZERO) // true
new BigDecimal("0.00").equals(BigDecimal.ZERO) // false!

поэтому он не подходит для чисто числового сравнения. Тем BigDecimal.compareTo()не менее, не учитывает масштаб при сравнении:

new BigDecimal("0").compareTo(BigDecimal.ZERO) == 0 // true
new BigDecimal("0.00").compareTo(BigDecimal.ZERO) == 0 // true

BigDecimal.ZERO.compareTo (цена) == 0
Jackkobec

97

В качестве альтернативы, signum () можно использовать:

if (price.signum() == 0) {
    return true;
}

21
Может быть, это быстрее, но CompareTo (BigDecimal.ZERO) более читабельно.
ElYeante

@ElYeante, вы всегда можете заключить это в метод, который имеет более читаемое имя или даже описывает часть вашей бизнес-логики, связанной с таким сравнением
WeGa

3
К сожалению, signum () не является нуль-безопасным, тогда как CompareTo - при сравнении с BigDecimal.ZERO.compareTo (), так что обратите на это внимание
WeGa

15
@WeGa Это не правда: BigDecimal.ZERO.compareTo(null)бросит NPE
ACV

5
@ACV, спасибо за вашу бдительность. Посмотрев исходный код, compareTo () действительно ожидает только ненулевой аргумент.
WeGa

24

Существует константа, с которой вы можете проверить:

someBigDecimal.compareTo(BigDecimal.ZERO) == 0

3
Запрашивается разрешение на кражу вашей терминологии «состояния Йоды».
SimplyPanda


Поведение Java BigDecimal equalsи compareToне так, как вы думаете. docs.oracle.com/javase/1.5.0/docs/api/java/math/…
nhahtdh

2
CompareTo от BigDecimal по-прежнему будет выдавать исключение, если вы передадите нулевое значение.
Джон Цзян

5

Я обычно использую следующее:

if (selectPrice.compareTo(BigDecimal.ZERO) == 0) { ... }

5

В качестве альтернативы, я думаю, стоит упомянуть, что поведение методов equals и compareTo в классе BigDecimal не соответствуют друг другу .

Это в основном означает, что:

BigDecimal someValue = new BigDecimal("0.00");
System.out.println(someValue.compareTo(BigDecimal.ZERO)==0); //true
System.out.println(someValue.equals(BigDecimal.ZERO)); //false

Поэтому вы должны быть очень осторожны со шкалой в вашей someValueпеременной, иначе вы получите неожиданный результат.


5

Вы хотели бы использовать equals (), так как они являются объектами, и использовать встроенный экземпляр ZERO:

if(selectPrice.equals(BigDecimal.ZERO))

Обратите внимание, что .equals()учитывается масштаб, поэтому, если selectPrice не имеет такой же масштаб (0), как .ZEROтогда, он вернет false.

Чтобы вывести масштаб из уравнения как бы:

if(selectPrice.compareTo(BigDecimal.ZERO) == 0)

Я должен отметить, что для определенных математических ситуаций 0.00 != 0, поэтому я предполагаю, что .equals()учитывает масштаб. 0.00дает точность до сотого места, а 0не так точно. В зависимости от ситуации вы можете придерживаться .equals().


Поведение Java BigDecimal equalsи compareToне так, как вы думаете. docs.oracle.com/javase/1.5.0/docs/api/java/math/…
nhahtdh

Не хочешь объяснить, что ты имеешь в виду вместо ссылки на документы? То, что я предложил, должно работать на ФП.
NominSim

Ответ Эдвина Далорсо объясняет это довольно хорошо, на самом деле. equalsучитывает масштаб, а это не то, что мы хотим здесь.
nhahtdh

@nhahtdh Спасибо за информацию, хотя есть ситуации, где equals следует использовать вместо compareTo(). ОП не указывает, какой тип математики он использует, поэтому вы правы, лучше дать ему оба варианта.
NominSim

3

GriffeyDog определенно прав:

Код:

BigDecimal myBigDecimal = new BigDecimal("00000000.000000");
System.out.println("bestPriceBigDecimal=" + myBigDecimal);
System.out.println("BigDecimal.valueOf(0.000000)=" + BigDecimal.valueOf(0.000000));
System.out.println(" equals=" + myBigDecimal.equals(BigDecimal.ZERO));
System.out.println("compare=" + (0 == myBigDecimal.compareTo(BigDecimal.ZERO)));

Полученные результаты:

myBigDecimal=0.000000
BigDecimal.valueOf(0.000000)=0.0
 equals=false
compare=true

Хотя я понимаю преимущества сравнения BigDecimal, я бы не стал рассматривать его как интуитивную конструкцию (как это делают операторы ==, <,>, <=,> =). Когда вы держите в своей голове миллион вещей (хорошо, семь вещей), тогда все, что вы можете уменьшить когнитивную нагрузку, - это хорошо. Поэтому я построил несколько полезных вспомогательных функций:

public static boolean equalsZero(BigDecimal x) {
    return (0 == x.compareTo(BigDecimal.ZERO));
}
public static boolean equals(BigDecimal x, BigDecimal y) {
    return (0 == x.compareTo(y));
}
public static boolean lessThan(BigDecimal x, BigDecimal y) {
    return (-1 == x.compareTo(y));
}
public static boolean lessThanOrEquals(BigDecimal x, BigDecimal y) {
    return (x.compareTo(y) <= 0);
}
public static boolean greaterThan(BigDecimal x, BigDecimal y) {
    return (1 == x.compareTo(y));
}
public static boolean greaterThanOrEquals(BigDecimal x, BigDecimal y) {
    return (x.compareTo(y) >= 0);
}

Вот как их использовать:

    System.out.println("Starting main Utils");
    BigDecimal bigDecimal0 = new BigDecimal(00000.00);
    BigDecimal bigDecimal2 = new BigDecimal(2);
    BigDecimal bigDecimal4 = new BigDecimal(4);  
    BigDecimal bigDecimal20 = new BigDecimal(2.000);
    System.out.println("Positive cases:");
    System.out.println("bigDecimal0=" + bigDecimal0 + " == zero is " + Utils.equalsZero(bigDecimal0));
    System.out.println("bigDecimal2=" + bigDecimal2 + " <  bigDecimal4=" + bigDecimal4 + " is " + Utils.lessThan(bigDecimal2, bigDecimal4));
    System.out.println("bigDecimal2=" + bigDecimal2 + " == bigDecimal20=" + bigDecimal20 + " is " + Utils.equals(bigDecimal2, bigDecimal20));
    System.out.println("bigDecimal2=" + bigDecimal2 + " <= bigDecimal20=" + bigDecimal20 + " is " + Utils.equals(bigDecimal2, bigDecimal20));
    System.out.println("bigDecimal2=" + bigDecimal2 + " <= bigDecimal4=" + bigDecimal4 + " is " + Utils.lessThanOrEquals(bigDecimal2, bigDecimal4));
    System.out.println("bigDecimal4=" + bigDecimal4 + " >  bigDecimal2=" + bigDecimal2 + " is " + Utils.greaterThan(bigDecimal4, bigDecimal2));
    System.out.println("bigDecimal4=" + bigDecimal4 + " >= bigDecimal2=" + bigDecimal2 + " is " + Utils.greaterThanOrEquals(bigDecimal4, bigDecimal2));
    System.out.println("bigDecimal2=" + bigDecimal2 + " >= bigDecimal20=" + bigDecimal20 + " is " + Utils.greaterThanOrEquals(bigDecimal2, bigDecimal20));
    System.out.println("Negative cases:");
    System.out.println("bigDecimal2=" + bigDecimal2 + " == zero is " + Utils.equalsZero(bigDecimal2));
    System.out.println("bigDecimal2=" + bigDecimal2 + " == bigDecimal4=" + bigDecimal4 + " is " + Utils.equals(bigDecimal2, bigDecimal4));
    System.out.println("bigDecimal4=" + bigDecimal4 + " <  bigDecimal2=" + bigDecimal2 + " is " + Utils.lessThan(bigDecimal4, bigDecimal2));
    System.out.println("bigDecimal4=" + bigDecimal4 + " <= bigDecimal2=" + bigDecimal2 + " is " + Utils.lessThanOrEquals(bigDecimal4, bigDecimal2));
    System.out.println("bigDecimal2=" + bigDecimal2 + " >  bigDecimal4=" + bigDecimal4 + " is " + Utils.greaterThan(bigDecimal2, bigDecimal4));
    System.out.println("bigDecimal2=" + bigDecimal2 + " >= bigDecimal4=" + bigDecimal4 + " is " + Utils.greaterThanOrEquals(bigDecimal2, bigDecimal4));

Результаты выглядят так:

Positive cases:
bigDecimal0=0 == zero is true
bigDecimal2=2 <  bigDecimal4=4 is true
bigDecimal2=2 == bigDecimal20=2 is true
bigDecimal2=2 <= bigDecimal20=2 is true
bigDecimal2=2 <= bigDecimal4=4 is true
bigDecimal4=4 >  bigDecimal2=2 is true
bigDecimal4=4 >= bigDecimal2=2 is true
bigDecimal2=2 >= bigDecimal20=2 is true
Negative cases:
bigDecimal2=2 == zero is false
bigDecimal2=2 == bigDecimal4=4 is false
bigDecimal4=4 <  bigDecimal2=2 is false
bigDecimal4=4 <= bigDecimal2=2 is false
bigDecimal2=2 >  bigDecimal4=4 is false
bigDecimal2=2 >= bigDecimal4=4 is false

1
Есть несколько ответов, объясняющих именно это. Какой смысл добавлять еще один ответ? Если у вас есть дополнительная информация, то стоит добавить новый ответ, но в этом посте это не так.
Том

Дело принято. Однако когда я что-то изучаю, мне нравится видеть как можно больше примеров, даже если они похожи. Для тебя, Том, я добавил свою библиотеку, которая мне показалась полезной. Ваш пробег может варьироваться. :-)
Тихамер

0

Просто хочу поделиться здесь некоторыми полезными расширениями для kotlin

fun BigDecimal.isZero() = compareTo(BigDecimal.ZERO) == 0
fun BigDecimal.isOne() = compareTo(BigDecimal.ONE) == 0
fun BigDecimal.isTen() = compareTo(BigDecimal.TEN) == 0

-2
BigDecimal.ZERO.setScale(2).equals(new BigDecimal("0.00"));

1
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему он решает проблему, улучшит долгосрочную ценность ответа. Помните, что вы отвечаете на вопрос для читателей в будущем, а не только для того, кто спрашивает сейчас! Пожалуйста, измените свой ответ, чтобы добавить объяснение и указать, какие ограничения и допущения применяются. Также не помешает упомянуть, почему этот ответ более уместен, чем другие.
Dev-

-8

Есть статическая константа, которая представляет 0 :

BigDecimal.ZERO.equals(selectPrice)

Вы должны сделать это вместо:

selectPrice.equals(BigDecimal.ZERO)

во избежание того случая, когда selectPriceесть null.


3
Поведение Java BigDecimal equalsи compareToне так, как вы думаете. docs.oracle.com/javase/1.5.0/docs/api/java/math/…
nhahtdh

так и для второй строки ... если selectedPrice имеет значение null, он просто выдаст исключение NullPointerException.
user3206236
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.