1. Pendahuluan
Untuk meminjam kata -kata dari buku "Effactive Java", tujuan desain utama float dan tipe ganda adalah untuk komputasi ilmiah dan komputasi teknik. Mereka melakukan operasi titik terapung biner, yang dirancang dengan hati-hati untuk memberikan perkiraan cepat yang lebih akurat di rentang numerik area lebar. Namun, mereka tidak memberikan hasil yang sepenuhnya akurat dan tidak boleh digunakan dalam situasi di mana hasil yang akurat diperlukan. Namun, perhitungan komersial sering membutuhkan hasil yang akurat, dan BigDecimal berguna saat ini.
2. Pengantar BigDecimal
BigDecimal terdiri dari nilai non-skala integer dari setiap presisi dan skala integer 32-bit. Jika nol atau positif, skalanya adalah jumlah digit setelah titik desimal. Jika itu adalah angka negatif, kalikan nilai non-skaling dari angka dengan kekuatan skala negatif 10. Oleh karena itu, nilai yang diwakili oleh BigDecimal adalah (unscaledValue × 10-skala).
3. Kode Uji
3.1 Konstruktor (Jenis parameter uji utama adalah dua konstruktor umum dengan ganda dan string)
Salinan kode adalah sebagai berikut: BigDecimal Adouble = BigDecimal baru (1.22);
System.out.println ("Konstruksi dengan nilai ganda:" + adouble);
Astring bigdecimal = BigDecimal baru ("1.22");
System.out.println ("Buat dengan nilai string:" + astring);
Menurut Anda apa outputnya? Jika Anda tidak berpikir yang pertama akan menghasilkan 1.22, maka ucapan selamat atas jawabannya dengan benar, hasil outputnya adalah sebagai berikut:
Salin Kode sebagai berikut: Bangun dengan Doublevalue: 1.219999999999999999733546474089962430298328399658203125
Bangun dengan nilai string: 1.22
Deskripsi JDK:
1. Hasil metode konstruksi dengan tipe parameter ganda tidak dapat diprediksi. Beberapa orang mungkin berpikir bahwa BigDecimal yang diciptakan dengan menulis newbigdecimal (0,1) di Java persis sama dengan 0,1 (nilai non-skaling 1, yang skalnya 1), tetapi sebenarnya sama dengan 0,1000000000000000000000000555115123125782702111581583404045554.256255782702121181583405551254.254.2541254827827827000000000000000.000 Ini karena 0,1 tidak dapat diekspresikan secara akurat sebagai ganda (atau untuk kasus ini tidak dapat dinyatakan sebagai desimal biner panjang terbatas). Dengan cara ini, nilai yang diteruskan ke dalam metode konstruksi tidak akan persis sama dengan 0,1 (meskipun permukaannya sama dengan nilai itu).
2. Di sisi lain, metode konstruksi string sepenuhnya dapat diprediksi: Menulis ke newBigDecimal ("0.1") akan menciptakan BigDecimal, yang persis sama dengan 0,1 yang diharapkan. Oleh karena itu, sebagai perbandingan, umumnya disarankan untuk menggunakan konstruktor string terlebih dahulu.
3. Ketika ganda harus digunakan sebagai sumber BigDecimal, harap dicatat bahwa konstruktor ini memberikan konversi yang akurat; Ini tidak memberikan hasil yang sama dengan operasi berikut: pertama -tama gunakan metode double.tostring (ganda), dan kemudian gunakan konstruktor BigDecimal (String) untuk mengonversi ganda ke string. Untuk mendapatkan hasilnya, gunakan metode statis (ganda) metode.
3.2 Operasi Penambahan
Salinan kode adalah sebagai berikut: BigDecimal A = BigDecimal baru ("1.22");
System.out.println ("Buat dengan nilai string:" + a);
BigDecimal B = BigDecimal baru ("2.22");
A.Add (b);
System.out.println ("Aplus B adalah:" + a);
Sangat mudah untuk berpikir bahwa itu akan menghasilkan:
Salin kode sebagai berikut: Bangun dengan StringValue: 1.22
A plus B adalah: 3.44
Tetapi sebenarnya A plus B adalah: 1.22
4. Analisis Kode Sumber
4.1 Nilai Metode (Doubleval)
Salin kode sebagai berikut: Nilai Public Static BigDecimal (Double Val) {
// Pengingat: Pengembalian Ganda Zero '0.0', jadi kami tidak dapat memperpanjang
// untuk menggunakan nol konstan. Ini mungkin cukup penting untuk
// membenarkan pendekatan pabrik, cache, atau beberapa pribadi
// Konstanta, nanti.
ReturnNew BigDecimal (double.tostring (val)); // Lihat poin ketiga dalam 3.1 tentang deskripsi JDK
}
4.2 Metode Tambah (BigDecimal Augend)
Publik BigDecimal Add (BigDecimal Augend) {long xs = this.intcompact; // BigDecimal diwakili oleh nomor integer, misalnya a memiliki nilai intompact 122 long ys = augend.IntCompact; // sama seperti di atas biginteger fst = (this.intcompact! = Diinflasi)? Null: this.intval; // inisialisasi nilai biginteger, intval adalah properti bigger. ! = Meningkat)? Null: augend.intval; int rscale = this.scale; // desimal tempat long sdiff = (long) rscale - augend.scale; // perbedaan antara tempat desimal jika (sdiff! = 0) {// tempat desimal dengan tempat desimal adalah hasilnya jika (sdiff <) {int raise = checkscale (-sdiff); rscale = augend.scale; if (xs == meningkat || (xs = longmultiplypowerten (xs, raise)) == meningkat) fst = bigMultiplypowerten (raise); } else {int raise = augend.checkscale (sDiff); if (ys == meningkat || (ys = longmultiplypowerten (ys, raise)) == meningkat) snd = augend.bigmultiplypowerten (raise); }} if (xs! = Inflated && ys! = Inflated) {long sum = xs + ys; if ((((sum ^ xs) & (sum ^ ys)))> = 0l) // menilai apakah ada overflow. Return BigDecimal.ValueOf (SUM, RCALE); // Kembalikan BigDecimal Instance yang diperoleh dengan menggunakan metode pabrik statis BigDecimal} if (fst == null) fst = BigInteger.ValueOf (xs); // Metode pabrik statis Biginteger if (snd == NULL); Biginteger sum = fst.add (snd); return (fst.signum == snd.signum)? baru bigdecimal (jumlah, inflated, rcale, 0): baru bigdecimal (sum, compactvalfor (sum), rcale, 0); // kembalikan objek besar yang diperoleh dengan metode konstruksi lain}Di atas hanyalah analisis kode sumber tambahan. Pengurangan, perkalian dan divisi sebenarnya mengembalikan objek BigDecimal baru. Karena BigInteger dan BigDecimal keduanya tidak dapat diubah, objek baru akan dihasilkan saat melakukan setiap langkah operasi, jadi A.Add (b); Meskipun operasi penambahan dilakukan, A tidak menyimpan nilai setelah operasi penambahan. Penggunaan yang benar harus a = a.add (b);
5. Ringkasan
(1) Perhitungan komersial menggunakan BigDecimal.
(2) Coba gunakan konstruktor dengan string tipe parameter.
(3) BigDecimals tidak dapat diubah. Saat melakukan setiap langkah operasi, objek baru akan dihasilkan. Oleh karena itu, saat melakukan penambahan, pengurangan, perkalian dan pembagian, Anda harus menyimpan nilai setelah operasi.
(4) Kami sering cenderung mengabaikan beberapa detail implementasi dari JDK yang mendasarinya, yang mengakibatkan kesalahan, jadi kami perlu lebih memperhatikan.
Referensi: Kelas BigDecimal