Memahami angka floating point (bagian 0)

Halo, orang Khabrovit. Saya sudah lama menyukai topik register floating point. Saya selalu khawatir tentang bagaimana output ke layar, dll. Saya ingat, dulu di universitas saya menerapkan kelas angka floating-point saya yang terdiri dari 512 bit. Satu-satunya hal yang tidak dapat saya sadari adalah output ke layar.

Segera setelah saya memiliki waktu luang, saya mengambil yang lama. Saya mendapatkan sebuah buku catatan dan segera berangkat. Saya ingin memikirkan semuanya sendiri, hanya sesekali melihat standar IEEE 754.
Dan inilah yang datang dari itu semua. Bagi yang berminat, saya minta kucing.

Untuk menguasai artikel ini, Anda perlu mengetahui yang berikut: apa itu bit, sistem biner, aritmatika pada tingkat pengetahuan derajat negatif. Artikel ini tidak akan memengaruhi detail rekayasa implementasi di tingkat prosesor serta nomor yang dinormalisasi dan dinormalkan. Penekanan lebih ditempatkan pada konversi angka menjadi bentuk biner dan sebaliknya, serta menjelaskan bagaimana angka floating point umumnya disimpan dalam bentuk bit.

Angka floating-point adalah alat yang sangat kuat yang Anda butuhkan untuk dapat menggunakannya dengan benar. Mereka tidak biasa seperti register bilangan bulat, tetapi juga tidak begitu rumit jika mereka secara kompeten dan perlahan ditembus.

Pada artikel hari ini, saya akan menggunakan register 32-bit sebagai contoh. Angka presisi ganda (64-bit) bekerja dengan logika yang persis sama.

Pertama, mari kita bicara tentang bagaimana angka floating point disimpan. 31 bit tertua adalah signifikan. Satu berarti angka itu negatif, dan nol, masing-masing, adalah kebalikannya. Berikutnya 8 bit eksponen. 8 bit ini adalah nomor unsigned yang biasa. Dan pada akhirnya adalah 23 bit mantissa. Untuk kenyamanan, kami menyatakan tanda sebagai S, eksponen sebagai E, dan mantissa, anehnya, M.

Kami mendapatkan formula umum (1)s kaliM kali2E127

Mantera dianggap sebagai satu bit implisit. Artinya, mantissa akan menjadi 24 bit, tetapi karena bit ke-23 tertinggi selalu satu, Anda tidak dapat menuliskannya. Dengan demikian, "pembatasan" ini akan memberi kita keunikan mewakili angka apa pun.

Mantissa adalah bilangan biner biasa, tetapi tidak seperti bilangan bulat, bit paling signifikan adalah 2 ^ 0 derajat dan kemudian dalam derajat menurun. Di sinilah peserta pameran berguna. Tergantung pada nilainya, kekuatan bit tinggi meningkat atau menurun. Itulah keseluruhan jenius dari ide ini.

Mari kita coba tunjukkan ini dengan contoh yang baik:

Bayangkan angka 3,625 dalam bentuk biner. Pertama, kami membagi angka ini menjadi dua kekuatan. 3,625=2+1+0,5+0,125=1 kali21+1 kali20+1 kali21+0 kali22+1 kali23

Tingkat dua senior sama dengan satu. E - 127 = 1. E = 128.

0 1.000.000 1.101.000.000.000.000.000.000.000.000

Itu semua nomor kita.

Mari kita coba juga di arah yang berlawanan. Misalkan kita memiliki 32 bit, sewenang-wenang 32 bit.

0 10000100 (1) 11011100101000000000000

Bit orde tinggi implisit yang sama ditunjukkan dalam tanda kurung.

Pertama, hitung eksponen. E = 132. Dengan demikian, tingkat dua senior akan sama dengan 5. Total kami memiliki nomor berikut:
25+24+23+21+20+21+24+26=
=32+16+8+2+1+0,5+0,0625+0,015625=59,578125

Mudah ditebak bahwa kita hanya bisa menyimpan kisaran 24 derajat dua. Dengan demikian, jika dua angka berbeda secara eksponensial lebih dari 24, maka ketika ditambahkan, jumlahnya tetap sama dengan yang lebih besar di antara mereka.

Untuk konversi yang nyaman, saya mengunggah program kecil di C.

#include <stdio.h> union IntFloat { unsigned int integerValue; float floatValue; }; void printBits(unsigned int x) { int i; for (i = 31; i >= 0; i--) { if ((x & ((unsigned int)1 << i)) != 0) { printf("1"); } else { printf("0"); } if (i == 31) { printf(" "); } if (i == 23) { printf(" "); } } printf("\n"); } int main() { union IntFloat b0; b0.floatValue = 59.578125; printBits(b0.integerValue); b0.integerValue = 0b01000010011011100101000000000000; printf("%f\n", b0.floatValue); return 0; } 

Langkah kisi adalah perbedaan minimum antara dua angka floating point yang berdekatan. Jika kita merepresentasikan urutan bit dari angka tersebut sebagai integer biasa, maka angka floating-point yang berdekatan akan berbeda dalam bit sebagai integer per unit.

Itu bisa dinyatakan sebaliknya. Dua angka floating point yang berdekatan akan berbeda 2 ^ (E - 127 - 23). Artinya, dengan perbedaan sama dengan nilai bit paling signifikan.

Sebagai bukti, Anda dapat mengubah kode utama dan mengkompilasi kembali.

 union IntFloat b0, b1, b2; b0.floatValue = 59.578125F; b1.integerValue = b0.integerValue + 1; b2.floatValue = b1.floatValue - b0.floatValue; printBits(b0.integerValue); printBits(b1.integerValue); printBits(b2.integerValue); printf("%f\n", b0.floatValue); printf("%f\n", b1.floatValue); printf("%f\n", b2.floatValue); short exp1 = 0b10000100; short exp2 =0b01101101; /*  ,       */ b0.integerValue = 0b01000010011111111111111111111111; b1.integerValue = b0.integerValue + 1; b2.floatValue = b1.floatValue - b0.floatValue; printBits(b0.integerValue); printBits(b1.integerValue); printBits(b2.integerValue); printf("%f\n", b0.floatValue); printf("%f\n", b1.floatValue); printf("%f\n", b2.floatValue); /*   */ printf("%d %d\n", exp1, exp2); 

Saya pikir untuk hari ini Anda bisa membulatkannya, kalau tidak ternyata terlalu lama. Lain kali saya akan menulis tentang menambahkan angka floating point dan kehilangan presisi saat pembulatan.

PS: Saya mengerti bahwa saya tidak menyentuh topik angka yang didenormalkan, dll. Saya hanya tidak ingin memuat artikel sangat banyak, dan informasi ini dapat dengan mudah ditemukan di standar IEEE 754 hampir di awal.

Source: https://habr.com/ru/post/id456714/


All Articles