Buka konsol JavaScript di browser dan ketik 0.1 + 0.2 — alih-alih 0.3, hasilnya adalah 0.30000000000000004. Ini bukan bug JavaScript — ini konsekuensi langsung dari cara standar IEEE 754 merepresentasikan bilangan pecahan dalam biner, dan hasil yang sama muncul di PHP, Python, Java, dan hampir semua bahasa lain yang dibangun di atas standar ini.
Tiga bagian bilangan floating-point
Bilangan menurut IEEE 754 disimpan sebagai tiga komponen: tanda (positif atau negatif), mantissa (digit signifikan bilangan), dan eksponen (pangkat yang menggeser titik desimal). Ini mirip dengan notasi ilmiah: 1.5 × 10², hanya dalam sistem biner.
Mengapa 0.1 tidak bisa direpresentasikan tepat dalam biner
0.1 dalam desimal adalah pecahan tak terhingga dalam biner (mirip dengan bagaimana 1/3 tak terhingga dalam desimal). Komputer hanya menyimpan sejumlah bit mantissa yang terbatas, jadi angka dibulatkan ke nilai terdekat yang bisa direpresentasikan — dan pembulatan inilah yang menyebabkan "galat" yang terlihat.
Di mana ini benar-benar merepotkan: saldo dompet digital
Aplikasi e-wallet yang menjumlahkan setiap transaksi sebagai float biasa bisa mengalami selisih beberapa rupiah dari saldo yang seharusnya setelah cukup banyak transaksi — setiap penjumlahan sedikit dibulatkan, dan galat ini menumpuk alih-alih saling meniadakan. Itulah sebabnya sistem pembayaran biasanya menghitung dalam satuan rupiah bulat (bukan pecahan), atau memakai tipe data decimal khusus, bukan menjumlahkan float mentah begitu saja.
Untuk apa ini dibutuhkan
- Memahami dan mendiagnosis galat pembulatan yang tidak terduga dalam perhitungan finansial atau ilmiah.
- Melihat representasi biner tepat dari bilangan floating-point tertentu.
- Menjelaskan kepada kolega atau mahasiswa mengapa membandingkan bilangan pecahan untuk kesetaraan tepat adalah praktik buruk.
Bilangan subnormal di dekat nol
Ketika nilai suatu angka terlalu kecil untuk representasi normal (signifikan yang dimulai dengan 1 implisit), IEEE 754 beralih ke mode subnormal (didenormalisasi), di mana 1 implisit ini dihilangkan — ini memungkinkan representasi angka yang lebih kecil lagi dalam magnitudo, dengan biaya kehilangan presisi secara bertahap alih-alih lompatan mendadak ke nol. Transisi "halus" ke nol ini lebih baik daripada nol mendadak, tapi perhitungan subnormal terasa lebih lambat daripada perhitungan normal pada beberapa prosesor.