Aritmatika floating-point

Selamat datang di bagian lain Under The Hood . Kolom ini bertujuan untuk memberikan gambaran sekilas kepada pengembang Java tentang keindahan tersembunyi di bawah program Java mereka yang sedang berjalan. Kolom bulan ini melanjutkan diskusi, dimulai bulan lalu, tentang set instruksi bytecode dari mesin virtual Java (JVM). Artikel ini membahas aritmatika floating-point di JVM, dan mencakup bytecode yang melakukan operasi aritmatika floating-point. Artikel selanjutnya akan membahas anggota lain dari keluarga bytecode.

Titik mengambang utama

Dukungan floating-point JVM mengikuti standar floating-point IEEE-754 1985. Standar ini mendefinisikan format angka floating-point 32-bit dan 64-bit dan mendefinisikan operasi pada angka-angka itu. Dalam JVM, aritmatika floating-point dilakukan pada float 32-bit dan ganda 64-bit. Untuk setiap bytecode yang melakukan aritmatika pada float, ada bytecode terkait yang melakukan operasi yang sama pada double.

Bilangan floating-point memiliki empat bagian - tanda, mantissa, radix, dan eksponen. Tandanya adalah 1 atau -1. Mantissa, selalu bilangan positif, memiliki digit signifikan dari bilangan floating-point. Eksponen menunjukkan pangkat positif atau negatif dari akar yang mantissa dan tanda harus dikalikan. Keempat komponen tersebut digabungkan sebagai berikut untuk mendapatkan nilai floating-point:

tanda * mantissa * eksponen radix

Bilangan floating-point memiliki beberapa representasi, karena seseorang selalu dapat mengalikan mantissa dari bilangan floating-point apa pun dengan beberapa pangkat akar dan mengubah eksponen untuk mendapatkan bilangan aslinya. Misalnya, bilangan -5 dapat diwakili secara merata oleh salah satu bentuk berikut dalam radix 10:

Bentuk -5
Tanda Mantissa Eksponen radix
-1 50 10 -1
-1 5 10 0
-1 0,5 10 1
-1 0,05 10 2

Untuk setiap bilangan floating-point ada satu representasi yang dikatakan dinormalisasi. Bilangan floating-point dinormalisasi jika mantisanya berada dalam kisaran yang ditentukan oleh relasi berikut:

1 / radix <= mantissa <

Bilangan floating-point radix 10 yang dinormalisasi memiliki titik desimalnya tepat di sebelah kiri digit bukan nol pertama di mantissa. Representasi floating-point yang dinormalisasi -5 adalah -1 * 0,5 * 10 1. Dengan kata lain, mantissa bilangan floating-point yang dinormalisasi tidak memiliki digit bukan nol di sebelah kiri koma desimal dan digit bukan nol hanya untuk di sebelah kanan koma desimal. Setiap bilangan floating-point yang tidak sesuai dengan kategori ini dikatakan dinormalisasi . Perhatikan bahwa angka nol tidak memiliki representasi yang dinormalisasi, karena tidak memiliki digit bukan nol untuk diletakkan tepat di sebelah kanan koma desimal. "Mengapa dinormalisasi?" adalah seruan umum di antara angka nol.

Angka floating-point di JVM menggunakan radix dua. Angka floating-point di JVM, oleh karena itu, memiliki bentuk sebagai berikut:

tanda * mantissa * 2 eksponen

Mantissa dari bilangan floating-point di JVM dinyatakan sebagai bilangan biner. Mantissa yang dinormalisasi memiliki titik binernya (basis dua yang setara dengan titik desimal) tepat di sebelah kiri digit bukan nol yang paling signifikan. Karena sistem bilangan biner hanya memiliki dua digit - nol dan satu - digit paling signifikan dari mantissa yang dinormalisasi selalu satu.

Bit yang paling signifikan dari float atau double adalah bit tandanya. Mantissa menempati 23 bit paling signifikan dari pelampung dan 52 bit paling signifikan dari pelampung. Eksponen, 8 bit dalam float dan 11 bit dalam double, berada di antara tanda dan mantissa. Format float ditampilkan di bawah ini. Bit tanda ditampilkan sebagai "s", bit eksponen ditampilkan sebagai "e", dan bit mantissa ditampilkan sebagai "m":

Tata letak bit Java float
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm

Sedikit tanda nol menunjukkan bilangan positif dan sedikit tanda satu menunjukkan bilangan negatif. Mantissa selalu diartikan sebagai bilangan basis dua positif. Ini bukan nomor pelengkap dua. Jika bit tanda satu, nilai floating-point bernilai negatif, tetapi mantissa tetap diartikan sebagai angka positif yang harus dikalikan -1.

Bidang eksponen diinterpretasikan dengan salah satu dari tiga cara. Eksponen semua yang menunjukkan bilangan floating-point memiliki salah satu nilai khusus plus atau minus tak terhingga, atau "bukan bilangan" (NaN). NaN adalah hasil operasi tertentu, seperti pembagian nol dengan nol. Eksponen semua nol menunjukkan bilangan floating-point yang dinormalisasi. Eksponen lainnya menunjukkan angka floating-point yang dinormalisasi.

Mantissa berisi satu bit presisi ekstra di luar yang muncul di bit mantissa. Mantissa pelampung, yang hanya menempati 23 bit, memiliki presisi 24 bit. Mantissa ganda, yang menempati 52 bit, memiliki presisi 53 bit. Bit mantissa paling signifikan dapat diprediksi, dan oleh karena itu tidak disertakan, karena eksponen bilangan floating-point di JVM menunjukkan apakah bilangan tersebut dinormalisasi atau tidak. Jika eksponen semuanya nol, bilangan floating-point dinormalisasi dan bit paling signifikan dari mantissa diketahui menjadi nol. Jika tidak, bilangan floating-point dinormalisasi dan bit mantissa yang paling signifikan dikenal sebagai satu.

JVM tidak mengeluarkan pengecualian sebagai hasil dari operasi floating-point apa pun. Nilai khusus, seperti positif dan negatif tak terhingga atau NaN, dikembalikan sebagai hasil operasi mencurigakan seperti pembagian dengan nol. Eksponen semuanya menunjukkan nilai floating-point khusus. Eksponen semua yang dengan mantissa yang semua bitnya nol menunjukkan tak terhingga. Tanda ketidakterbatasan ditunjukkan dengan bit tanda. Eksponen semua satu dengan mantissa lainnya diartikan sebagai "bukan angka" (NaN). JVM selalu menghasilkan mantissa yang sama untuk NaN, yang semuanya nol kecuali untuk mantissa bit paling signifikan yang muncul di nomor tersebut. Nilai-nilai ini ditampilkan untuk float di bawah ini:

Nilai float khusus
Nilai Bit mengambang (tanda eksponen mantissa)
+ Tak terbatas 0 11111111 00000000000000000000000
-Infinity 1 11111111 00000000000000000000000
NaN 1 11111111 10000000000000000000000

Eksponen yang tidak semuanya satu atau semua nol menunjukkan pangkat dua yang digunakan untuk mengalikan mantisa yang dinormalisasi. Pangkat dua dapat ditentukan dengan menafsirkan bit eksponen sebagai bilangan positif, dan kemudian mengurangkan bias dari bilangan positif. Untuk pelampung, biasnya 126. Untuk ganda, biasnya 1023. Misalnya, bidang eksponen dalam pelampung 00000001 menghasilkan pangkat dua dengan mengurangi bias (126) dari bidang eksponen yang diinterpretasikan sebagai bilangan bulat positif (1). Pangkat dua, oleh karena itu, adalah 1 - 126, yaitu -125. Ini adalah kekuatan terkecil yang mungkin dari dua pelampung. Di sisi lain, bidang eksponen 11111110 menghasilkan pangkat dua (254 - 126) atau 128. Angka 128 adalah pangkat dua terbesar yang tersedia untuk pelampung. Beberapa contoh float yang dinormalisasi ditunjukkan pada tabel berikut:

Nilai float yang dinormalkan
Nilai Bit mengambang (tanda eksponen mantissa) Eksponen yang tidak memihak
Pelampung positif (terbatas) terbesar 0 11111110 11111111111111111111111 128
Pelampung negatif (terbatas) terbesar 1 11111110 11111111111111111111111 128
Float ternormalisasi terkecil 1 00000001 00000000000000000000000 -125
Pi 0 10000000 10010010000111111011011 2

Eksponen semua nol menunjukkan mantissa didenormalisasi, yang berarti bit depan yang tidak dinyatakan adalah nol, bukan satu. Pangkat dua dalam hal ini sama dengan pangkat terendah dari dua yang tersedia untuk mantissa yang dinormalisasi. Untuk pelampung, ini adalah -125. Ini berarti bahwa mantisa yang dinormalisasi dikalikan dengan dua pangkat -125 memiliki bidang eksponen 00000001, sedangkan mantisa yang dinormalisasi dikalikan dengan dua pangkat -125 memiliki bidang eksponen 00000000. Penyisihan untuk bilangan yang dinormalisasi di bagian bawah akhir kisaran eksponen mendukung aliran bawah secara bertahap. Jika eksponen terendah digunakan untuk mewakili angka yang dinormalisasi, aliran bawah ke nol akan terjadi untuk angka yang lebih besar. Dengan kata lain, meninggalkan eksponen terendah untuk angka yang dinormalisasi memungkinkan angka yang lebih kecil untuk diwakili.Angka yang lebih kecil dinormalisasi memiliki bit yang lebih sedikit daripada angka yang dinormalisasi, tetapi ini lebih disukai daripada mengalir ke nol segera setelah eksponen mencapai nilai normalisasi minimum.

Nilai float yang didenormalisasi
Nilai Bit mengambang (tanda eksponen mantissa)
Pelampung positif terkecil (bukan nol) 0 00000000 00000000000000000000001
Pelampung negatif terkecil (bukan nol) 1 00000000 00000000000000000000001
Pelampung denormalisasi terbesar 100000000 11111111111111111111111
Nol positif 0 00000000 00000000000000000000000
Nol negatif 1 00000000 00000000000000000000000

Pelampung terbuka

Float Java mengungkapkan sifat dalamnya. Applet di bawah memungkinkan Anda bermain-main dengan format floating-point. Nilai float ditampilkan dalam beberapa format. Format notasi ilmiah radix dua menunjukkan mantissa dan eksponen dalam basis sepuluh. Sebelum ditampilkan, mantisa aktual dikalikan dengan 2 24, yang menghasilkan bilangan integral, dan eksponen yang tidak bias dikurangi dengan 24. Baik mantisa integral dan eksponen kemudian dengan mudah diubah menjadi basis sepuluh dan ditampilkan.