Як перевірити, чи змінна BigDecimal == 0 у Java?


202

У мене на Java такий код;

BigDecimal price; // assigned elsewhere

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

Який найкращий спосіб записати умову if?


12
Багато відповідей свідчать про використання методу .equals () BigDecimal. Але цей метод враховує масштаб, тому не є еквівалентним використанню CompareTo ().
GriffeyDog

Відповіді:


472

Використовуйте compareTo(BigDecimal.ZERO)замість equals():

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

Якщо порівнювати з BigDecimalконстантою, BigDecimal.ZEROуникнути необхідності будувати new BigDecimal(0)кожне виконання.

FYI, 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
Можливо, це швидше, але порівнятиTo (BigDecimal.ZERO) є більш читабельним.
ElYeante

@ElYeante, ти завжди можеш обробити це методом, який має більш читабельну назву, або навіть описує частину твоєї бізнес-логіки, пов'язану з таким порівнянням
WeGa

3
Unfortuntely 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
Потрібний дозвіл на викрадення вашої термінології "умова Yoda".
SimplyPanda


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

2
Порівняння BigDecimalTo все одно викине виняток, якщо ви перейдете до нуля.
Джон Цзян

5

Зазвичай я використовую таке:

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

5

Як варіант, я думаю, що варто згадати, що поведінка рівних та методів порівнянняДо класу 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тоді, це поверне помилкове значення.

Для виведення шкали з рівняння як би:

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-iL

-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

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