BigDecimal sama dengan () versus compareTo ()

157

Pertimbangkan kelas tes sederhana:

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

}

Anda dapat (secara sadar) mengatakan bahwa xitu sama dengan y(bukan referensi objek), tetapi ketika Anda menjalankan program, hasil berikut menunjukkan:

false
true

Pertanyaan: Apa perbedaan antara compareTo()dan equals()di dalam BigDecimalyang compareTodapat menentukan yang xsama dengan y?

PS: Saya melihat bahwa BigDecimal memiliki inflate()metode equals()metode. Sebenarnya apa yang inflate()dilakukan?

Buhake Sindi
sumber
1
Iklan inflate(): ini bukan bagian dari API publik karena hanya memanipulasi representasi internal dan tidak memiliki efek yang terlihat ke "luar". Jadi, kecuali Anda benar-benar ingin mempelajari implementasi BigDecimalmendalam, saya sarankan Anda mengabaikan metode ini.
Joachim Sauer
Penjelasan singkat dan cuplikan kode sumber dapat ditemukan di sini
xenteros

Jawaban:

224

Jawabannya ada di JavaDoc dari equals()metode :

Tidak seperti compareTo, metode ini menganggap dua BigDecimalobjek sama hanya jika mereka sama dalam nilai dan skala (dengan demikian 2.0 tidak sama dengan 2,00 bila dibandingkan dengan metode ini).

Dengan kata lain: equals()memeriksa apakah BigDecimalobjek sama persis di setiap aspek. compareTo()"hanya" membandingkan nilai numerik mereka.

Seperti mengapa equals() berperilaku seperti ini, ini telah dijawab dalam pertanyaan SO ini .

Joachim Sauer
sumber
24
Itu bagian yang sangat sulit BigDecimaljika Anda tidak membaca JavaDoc dengan cermat. :) - Kami mendapat beberapa bug aneh dari ini sampai kami menyadari perbedaannya.
Thomas
3
Banyak bagian dari API standar terjadi untuk bertindak "tidak sengaja", ketika hal intuitif tidak akan benar. BigDecimaladalah satu hal seperti itu. Karena itu kita harus selalu memeriksa JavaDoc. Setidaknya sekali Anda mengetahui sesuatu yang aneh sedang terjadi.
Joachim Sauer
7
Lucu. Setelah membaca jawaban Anda, saya baru saja memeriksa Sebanding dan menyatakan bahwa konsistensi dengan sama dengan "sangat disarankan (tetapi tidak wajib)"
SJuan76
4
Saya telah bertanya mengapa: stackoverflow.com/questions/14102083/…
bacar
8
@StephenC Saya pikir itu tidak benar bahwa ada ketidakkonsistenan ini.
Matt R
1

Saya melihat bahwa BigDecimal memiliki metode mengembang () pada equals () metode. Apa yang dilakukan mengembang () sebenarnya?

Pada dasarnya, inflate()panggilanBigInteger.valueOf(intCompact) jika perlu, yaitu menciptakan nilai yang tidak dihitung yang disimpan sebagai BigIntegerdari long intCompact. Jika Anda tidak membutuhkannya BigIntegerdan nilai unscaled cocok dengan long BigDecimaltampaknya mencoba menghemat ruang selama mungkin.

Thomas
sumber
Saya tidak tahu apa yang Anda tulis (terutama dengan kalimat terakhir).
Buhake Sindi
@The Elite Gentlement Kalimat terakhir seharusnya hanya mengatakan bahwa secara internal BigDecimalmenyimpan nilai yang tidak berskala dalam longa BigInteger. Jika BigIntegertidak diperlukan secara internal, itu tidak dibuat tetapi jika diperlukan (misalnya ketika equalsmenghadapi inflasi yang meningkat dan yang tidak meningkat BigDecimal) () `digunakan untuk membuatnya - Singkatnya: inflate()menangani konversi internal jika perlu dan karena itu bersifat pribadi, seharusnya tidak masalah bagi pengguna kelas
Thomas
1

Saya percaya bahwa jawaban yang benar adalah membuat dua angka (BigDecimals), memiliki skala yang sama, maka kita dapat memutuskan tentang kesetaraan mereka. Sebagai contoh, apakah kedua angka ini sama?

1.00001 and 1.00002

Yah, itu tergantung pada skalanya. Pada skala 5 (5 poin desimal), tidak ada mereka tidak sama. tetapi pada precimal desimal yang lebih kecil (skala 4 dan lebih rendah) mereka dianggap sama. Jadi saya sarankan untuk membuat skala kedua angka sama dan kemudian membandingkannya.

Mr.Q
sumber
-10

Anda juga dapat membandingkan dengan nilai ganda

BigDecimal a= new BigDecimal("1.1"); BigDecimal b =new BigDecimal("1.1");
System.out.println(a.doubleValue()==b.doubleValue());
Rashmi singh
sumber
5
Harap hindari solusi ini sebanyak mungkin. Bahkan ganda harus dibandingkan dengan "epsilon". Tidak ada gunanya memiliki BigDecimal dan membandingkannya sebagai ganda .. ada kemungkinan sangat besar Anda akan menembak kaki Anda sendiri.
Vadim Kirilchuk
Nilai ganda harus dibandingkan menggunakan epsillons
Bishwajit Purkaystha