Saya baru-baru ini mempelajari masalah perhitungan floating-point Java, menanyakan informasi yang relevan dari Internet, merangkum dan melakukan beberapa penyortiran dan debugging, dan akhirnya menyelesaikan artikel ini. Setiap orang dipersilakan untuk menunjukkan kesalahan dan masalahnya.
Di Java, variabel yang dideklarasikan dengan float adalah bilangan floating point presisi tunggal, dan variabel yang dideklarasikan dengan double adalah bilangan floating point presisi ganda. Sesuai dengan namanya, entitas tipe ganda menempati dua kali ruang memori float. float adalah 4 byte dan double adalah 8 byte. Data bertipe float dan double tidak dapat mewakili hasil perhitungan secara akurat, hal ini dikarenakan perhitungan float dan double tidak tepat. Anda dapat melihatnya melalui kode berikut:
Copy kode kodenya sebagai berikut:
Tes kelas publik
{
public static void main(String[] args)
{
Sistem.keluar.println(0,05 + 0,01);
Sistem.keluar.println(1.0 - 0.42);
Sistem.keluar.println(4.015*100);
Sistem.keluar.println(123.3 / 100);
}
}
Hasil dari menjalankannya adalah:
0,060000000000000005
0,5800000000000001
401.49999999999994
1.23299999999999999
Untuk mendapatkan efek yang diinginkan, kita bisa mencoba menggunakan java.text.DecimalFormat untuk memformat angka floating point:
DecimalFormat dapat memformat angka sesuai format tertentu. Karakter pemformatan yang umum digunakan adalah #, 0, dst. contoh:
Copy kode kodenya sebagai berikut:
System.out.println(java.text.DecimalFormat("0.00").format(3.125));
System.out.println(java.text.DecimalFormat("0.00").format(3.135));
Namun hasilnya adalah:
3.12
3.14
Hal ini karena DecimalFormat menggunakan pembulatan setengah genap (ROUND_HALF_EVEN). Sederhananya, DecimalFormat mengandalkan bilangan genap terdekat saat pembulatan ke 5. Oleh karena itu, angka floating point yang andal tidak dapat diperoleh menggunakan DecimalForamt. Terakhir, kami dapat mempertimbangkan penggunaan BigDecimal untuk penghitungan yang lebih akurat:
BigDecimal menyediakan banyak konstruktor, terkait dengan bilangan floating point:
Copy kode kodenya sebagai berikut:
BigDecimal(double val) Menerjemahkan double menjadi BigDecimal.
BigDecimal(String val) Menerjemahkan representasi String dari BigDecimal menjadi BigDecimal.
Namun, menggunakan parameter ganda untuk membuat objek akan menghasilkan nilai yang tidak akurat. Hanya pembuatan objek melalui String yang paling akurat.
Misalnya:
Copy kode kodenya sebagai berikut:
BigDecimal bd1=BigDecimal baru(0,05);
Sistem.keluar.println(bd1.toString());
BigDecimal bd2=BigDecimal baru("0,05");
Sistem.keluar.println(bd2.toString());
Dapatkan hasilnya:
0,05000000000000000277555756156289135105907917022705078125
0,05
Oleh karena itu, pada akhirnya kita perlu menggunakan String untuk membuat objek, agar hasil yang diperoleh paling akurat. Selain itu, jika bilangan ganda, kita juga dapat menggunakan: BigDecimal.valueOf(double val). Alasannya sangat sederhana. Kode sumber JDK adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
nilai BigDecimal statis publik(val ganda)
{
kembalikan BigDecimal baru(Double.toString(val));
}
Hal terakhir yang perlu diperhatikan adalah: penjumlahan, pengurangan, perkalian, dan pembagian BigDecimal pada akhirnya mengembalikan objek BigDecimal baru. Karena BigDecimal tidak dapat diubah, objek baru akan dihasilkan selama setiap operasi, jadi .add(b); dilakukan, a tidak menyimpan nilai setelah operasi penambahan. Penggunaan yang benar adalah a=a.add(b).