Saya harus menghitung beberapa variabel floating point dan kolega saya menyarankan saya untuk menggunakan BigDecimal
alih-alih double
karena akan lebih tepat. Tapi saya ingin tahu apa itu dan bagaimana memanfaatkannya BigDecimal
?
java
floating-point
double
bigdecimal
Truong Ha
sumber
sumber
Jawaban:
A
BigDecimal
adalah cara yang tepat untuk merepresentasikan angka. ADouble
memiliki presisi tertentu. Bekerja dengan dobel dari berbagai besaran (katakand1=1000.0
dand2=0.001
) dapat mengakibatkan0.001
dijatuhkan secara bersamaan ketika dijumlahkan karena perbedaan besarnya sangat besar. DenganBigDecimal
ini tidak akan terjadi.Kerugiannya
BigDecimal
adalah bahwa itu lebih lambat, dan itu sedikit lebih sulit untuk memprogram algoritma seperti itu (karena+
-
*
dan/
tidak kelebihan beban).Jika Anda berurusan dengan uang, atau ketepatan adalah suatu keharusan, gunakan
BigDecimal
. Kalau tidak,Doubles
cenderung cukup baik.Saya sarankan membaca javadoc dari
BigDecimal
seperti yang mereka lakukan menjelaskan hal-hal yang lebih baik daripada yang saya lakukan di sini :)sumber
if (Math.abs(loadPerServer - maxLoadPerServer) < 0.000001d) {
BigDecimal
", Double akan memiliki lebih banyak "presisi" (lebih banyak digit).Bahasa Inggris saya tidak bagus jadi saya hanya akan menulis contoh sederhana di sini.
Output program:
Adakah yang masih ingin menggunakan dobel? ;)
sumber
System.out.println(0.003f - 0.002f);
BigDecimal tepat:System.out.println(new BigDecimal("0.003").subtract(new BigDecimal("0.002")));
Ada dua perbedaan utama dari ganda:
Alasan Anda harus menggunakan BigDecimal untuk perhitungan moneter bukan karena ia dapat mewakili angka apa pun, tetapi ia dapat mewakili semua angka yang dapat direpresentasikan dalam konsep desimal dan yang mencakup hampir semua angka dalam dunia moneter (Anda tidak pernah mentransfer 1/3 $ untuk seseorang).
sumber
Jika Anda menuliskan nilai pecahan seperti
1 / 7
nilai desimal yang Anda dapatkandengan urutan tak terbatas
142857
. Karena Anda hanya dapat menulis jumlah digit terbatas, Anda pasti akan membuat kesalahan pembulatan (atau pemotongan).Angka seperti
1/10
atau1/100
dinyatakan sebagai angka biner dengan bagian fraksional juga memiliki jumlah digit tak terbatas setelah titik desimal:Doubles
menyimpan nilai-nilai sebagai biner dan karena itu dapat memperkenalkan kesalahan semata-mata dengan mengubah angka desimal menjadi angka biner, tanpa melakukan aritmatika apa pun.Angka desimal (seperti
BigDecimal
), di sisi lain, menyimpan setiap angka desimal apa adanya. Ini berarti bahwa jenis desimal tidak lebih tepat daripada titik mengambang biner atau tipe titik tetap dalam arti umum (yaitu tidak dapat menyimpan1/7
tanpa kehilangan presisi), tetapi lebih akurat untuk angka yang memiliki jumlah terbatas angka desimal sebagai sering terjadi untuk perhitungan uang.Jawa
BigDecimal
memiliki keuntungan tambahan yang dapat memiliki sewenang-wenang (namun terbatas) jumlah digit di kedua sisi titik desimal, hanya dibatasi oleh memori yang tersedia.sumber
BigDecimal adalah perpustakaan numerik presisi arbitrer Oracle. BigDecimal adalah bagian dari bahasa Jawa dan berguna untuk berbagai aplikasi mulai dari yang finansial hingga yang ilmiah (di situlah saya ada).
Tidak ada yang salah dengan menggunakan ganda untuk perhitungan tertentu. Misalkan, Anda ingin menghitung Math.Pi * Math.Pi / 6, yaitu, nilai Riemann Zeta Function untuk argumen nyata dua (proyek yang sedang saya kerjakan). Divisi floating-point memberi Anda masalah kesalahan pembulatan yang menyakitkan.
BigDecimal, di sisi lain, mencakup banyak opsi untuk menghitung ekspresi dengan ketepatan arbitrer. Metode tambah, gandakan, dan bagi seperti dijelaskan dalam dokumentasi Oracle di bawah ini "take the place" dari +, *, dan / di BigDecimal Java World:
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
Metode compareTo sangat berguna untuk while dan untuk loop.
Namun, berhati-hatilah dalam penggunaan konstruktor untuk BigDecimal. Konstruktor string sangat berguna dalam banyak kasus. Misalnya, kodenya
BigDecimal onethird = BigDecimal baru ("0.33333333333");
menggunakan representasi string 1/3 untuk mewakili nomor berulang berulang hingga tingkat akurasi yang ditentukan. Kesalahan pembulatan kemungkinan besar terjadi di suatu tempat yang jauh di dalam JVM sehingga kesalahan pembulatan tidak akan mengganggu sebagian besar perhitungan praktis Anda. Namun, dari pengalaman pribadi saya, saya melihat banyak hal. Metode setScale penting dalam hal ini, seperti yang dapat dilihat dari dokumentasi Oracle.
sumber
/* * Portions Copyright IBM Corporation, 2001. All Rights Reserved. */
Jika Anda berurusan dengan perhitungan, ada undang-undang tentang bagaimana Anda harus menghitung dan presisi apa yang harus Anda gunakan. Jika Anda gagal Anda akan melakukan sesuatu yang ilegal. Satu-satunya alasan sebenarnya adalah bahwa representasi bit dari kasus desimal tidak tepat. Seperti yang dikatakan Basil, sebuah contoh adalah penjelasan terbaik. Hanya untuk melengkapi contohnya, inilah yang terjadi:
Keluaran:
Kami juga memiliki itu:
Memberi kami hasilnya:
Tapi:
Memiliki output:
sumber