Bagaimana cara memeriksa apakah variabel BigDecimal == 0 di java?


202

Saya memiliki kode berikut di Jawa;

BigDecimal price; // assigned elsewhere

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

Apa cara terbaik untuk menulis kondisi if?


12
Banyak jawaban menyarankan menggunakan metode .equals () BigDecimal. Tapi metode itu mempertimbangkan skala, jadi tidak setara dengan menggunakan compareTo ().
GriffeyDog

Jawaban:


473

Gunakan compareTo(BigDecimal.ZERO)alih-alih equals():

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

Membandingkan dengan BigDecimalkonstanta BigDecimal.ZEROmenghindari harus membangun new BigDecimal(0)setiap eksekusi.

FYI, BigDecimaljuga memiliki konstanta BigDecimal.ONEdan BigDecimal.TENuntuk kenyamanan Anda.


Catatan!

Alasan Anda tidak bisa digunakan BigDecimal#equals()adalah bahwa dibutuhkan skala menjadi pertimbangan:

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

jadi tidak cocok untuk perbandingan murni numerik. Namun, BigDecimal.compareTo()tidak mempertimbangkan skala saat membandingkan:

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

BigDecimal.ZERO.compareTo (price) == 0
Jackkobec

97

Atau, signum () dapat digunakan:

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

21
Mungkin lebih cepat, tetapi bandingkanTo (BigDecimal.ZERO) lebih mudah dibaca.
ElYeante

@ ElYeante, Anda selalu dapat membungkus ini dengan metode, yang memiliki nama lebih mudah dibaca, atau bahkan menggambarkan bagian dari logika bisnis Anda, terhubung dengan perbandingan seperti itu
WeGa

3
Sayangnya signum () bukan null-safe, sedangkan compareTo adalah, ketika membandingkan seperti BigDecimal.ZERO.compareTo (), jadi perhatikan itu
WeGa

15
@WeGa Itu tidak benar: BigDecimal.ZERO.compareTo(null)akan melempar NPE
ACV

5
@ ACV, terima kasih atas kewaspadaan Anda. Melihat kode sumber, compareTo () hanya mengharapkan argumen yang bukan nol.
WeGa


5

Saya biasanya menggunakan yang berikut ini:

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

5

Atau, saya pikir perlu disebutkan bahwa perilaku metode equals dan compareTo di kelas BigDecimal tidak konsisten satu sama lain .

Ini pada dasarnya berarti:

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

Karena itu, Anda harus sangat berhati-hati dengan skala dalam someValuevariabel Anda , jika tidak, Anda akan mendapatkan hasil yang tidak terduga.


5

Anda ingin menggunakan equals () karena mereka adalah objek, dan menggunakan instance ZERO bawaan:

if(selectPrice.equals(BigDecimal.ZERO))

Perhatikan bahwa .equals()memperhitungkan skala, jadi kecuali selectPrice memiliki skala yang sama (0).ZERO maka ini akan mengembalikan false.

Untuk menghilangkan skala dari persamaan:

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

Saya harus mencatat bahwa untuk situasi matematika tertentu 0.00 != 0, itulah sebabnya saya bayangkan .equals()memperhitungkan skala. 0.00memberikan ketepatan ke tempat seratus, sedangkan 0tidak begitu tepat. Tergantung pada situasi yang Anda mungkin ingin pertahankan .equals().


Perilaku Java BigDecimal tentang equalsdan compareTotidak seperti yang Anda pikirkan. docs.oracle.com/javase/1.5.0/docs/api/java/math/…
nhahtdh

Ingin menjelaskan maksud Anda alih-alih menautkan ke dokumen? Apa yang saya sarankan harus bekerja untuk OP.
NominSim

Jawaban Edwin Dalorzo menjelaskannya dengan cukup baik, sebenarnya. equalsmempertimbangkan skala, yang bukan yang kita inginkan di sini.
nhahtdh

@nhahtdh Terima kasih atas informasinya, sebenarnya meskipun ada situasi di mana equals harus digunakan alih-alih compareTo(). OP tidak menentukan jenis matematika apa yang ia gunakan, jadi Anda benar lebih baik memberinya kedua opsi.
NominSim

3

GriffeyDog pasti benar:

Kode:

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

Hasil:

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

Sementara saya memahami keuntungan dari perbandingan BigDecimal, saya tidak akan menganggapnya sebagai konstruksi intuitif (seperti operator ==, <,>, <=,> =). Ketika Anda memegang sejuta hal (ok, tujuh hal) di kepala Anda, maka apa pun yang Anda dapat mengurangi beban kognitif Anda adalah hal yang baik. Jadi saya membangun beberapa fungsi kenyamanan yang bermanfaat:

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

Berikut cara menggunakannya:

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

Hasilnya terlihat seperti ini:

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
Ada beberapa jawaban yang menjelaskan hal itu. Apa gunanya menambahkan jawaban lain? Jika Anda memiliki informasi tambahan, maka itu ide yang baik untuk menambahkan jawaban baru, tetapi ini tidak terjadi dalam posting ini.
Tom

Poin yang diambil. Namun, ketika saya mempelajari sesuatu, saya suka melihat sebanyak mungkin contoh, bahkan jika mereka serupa. Bagi Anda, Tom, saya menambahkan perpustakaan saya yang saya temukan berguna. Jarak Anda mungkin beragam. :-)
Tihamer

0

Hanya ingin berbagi di sini beberapa ekstensi bermanfaat untuk 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
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang bagaimana dan / atau mengapa memecahkan masalah akan meningkatkan nilai jangka panjang jawaban. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, bukan hanya orang yang bertanya sekarang! Harap edit jawaban Anda untuk menambahkan penjelasan, dan berikan indikasi batasan dan asumsi apa yang berlaku. Tidak ada salahnya untuk menyebutkan mengapa jawaban ini lebih tepat daripada yang lain.
Dev-iL

-8

Ada konstanta statis yang mewakili 0 :

BigDecimal.ZERO.equals(selectPrice)

Anda harus melakukan ini alih-alih:

selectPrice.equals(BigDecimal.ZERO)

untuk menghindari kasus di mana selectPriceadalah null.


3
Perilaku Java BigDecimal tentang equalsdan compareTotidak seperti yang Anda pikirkan. docs.oracle.com/javase/1.5.0/docs/api/java/math/…
nhahtdh

jadi untuk baris kedua ... jika terpilihHarga adalah nol maka itu hanya akan melempar NullPointerException.
user3206236
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.