Aritmetika s pomičnom zarezom

Dobrodošli u još jedan dio Under the Hood . Ovaj stupac želi pružiti programerima Java uvid u skrivenu ljepotu ispod njihovih pokrenutih Java programa. Ovomjesečni stupac nastavlja raspravu, započetu prošlog mjeseca, o skupu naredbi bajt-koda Java virtualnog stroja (JVM). Ovaj članak analizira aritmetiku s pomičnom zarezom u JVM-u i pokriva bajt kodove koji izvode aritmetičke operacije s pomičnom zarezom. U sljedećim člancima raspravljat će se o ostalim članovima obitelji bajt kodova.

Glavne plutajuće točke

JVM-ova podrška s pomičnom zarezom pridržava se standarda IEEE-754 1985 s pomičnom zarezom. Ovaj standard definira format 32-bitnih i 64-bitnih brojeva s pomičnom zarezom i definira operacije nad tim brojevima. U JVM-u aritmetika s pomičnim zarezom izvodi se na 32-bitnim plovcima i 64-bitnim parovima. Za svaki bytecode koji izvodi aritmetiku na floats, postoji odgovarajući bytecode koji izvodi istu operaciju na parovima.

Broj s pomičnom zarezom ima četiri dijela - znak, mantisu, radiks i eksponent. Znak je ili 1 ili -1. Mantisa, uvijek pozitivan broj, sadrži značajne znamenke broja s pokretnom zarezom. Eksponent označava pozitivnu ili negativnu snagu radiksa s kojim se mantisa i znak moraju pomnožiti. Četiri se komponente kombiniraju na sljedeći način da bi se dobila vrijednost s pomičnim zarezom:

znak * mantissa * radix eksponent

Brojevi s pomičnom zarezom imaju više prikaza, jer se uvijek može množiti mantisu bilo kojeg broja s pomičnom zarezom nekom snagom radiksa i mijenjati eksponent da bi se dobio izvorni broj. Na primjer, broj -5 može biti jednako predstavljen bilo kojim od sljedećih oblika u radixu 10:

Oblici -5
Znak Kazaljka Radix eksponent
-1 50 10 -1
-1 5 10 0
-1 0,5 10 1
-1 0,05 10 2

Za svaki broj s pomičnom zarezom postoji jedan prikaz za koji se kaže da je normaliziran. Broj s pomičnom zarezom normalizira se ako je njegova mantisa unutar raspona definiranog sljedećom relacijom:

1 / radix <= mantissa <

Normalizirani broj s pomičnom zarezom u radixu 10 ima decimalnu zarez točno lijevo od prve znamenke koja nije nula u mantissi. Normalizirani prikaz s pomičnom zarezom od -5 je -1 * 0,5 * 10 1. Drugim riječima, mantisa normaliziranog broja s pomičnim zarezom nema znamenke koje nisu nula lijevo od decimalne točke, a cifra koja nije nula samo za desno od decimalne točke. Za svaki broj s pomičnom zarezom koji se ne uklapa u ovu kategoriju kaže se da je denormaliziran . Imajte na umu da broj nula nema normalizirani prikaz, jer nema znamenku koja nije nula i koja bi se stavila desno od decimalne točke. "Zašto se normalizira?" je čest uzvik među nulama.

Brojevi s pomičnom zarezom u JVM-u koriste polumjer dva. Brojevi s pomičnom zarezom u JVM-u, prema tome, imaju sljedeći oblik:

znak * mantissa * 2 eksponent

Mantisa broja s pomičnom zarezom u JVM-u izražava se kao binarni broj. Normalizirana mantisa ima svoju binarnu točku (osnovna dva ekvivalenta decimalne točke) s lijeve strane najznačajnije znamenke koja nije nula. Budući da binarni brojevni sustav ima samo dvije znamenke - nulu i jednu - najznačajnija znamenka normalizirane mantise uvijek je jedna.

Najznačajniji bit float-a ili double-a je njegov bit bit. Mantisa zauzima 23 najmanje značajna bita plovka i 52 najmanje značajna bita duplog. Eksponent, 8 bita u plovku i 11 bita u dvostrukom, nalazi se između znaka i mantise. Format plovka prikazan je u nastavku. Znakovni bit prikazan je kao "s", bitovi eksponenta prikazani su kao "e", a bitovi mantise prikazani su kao "m":

Izgled bita Java float-a
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm

Znakovni bit nule označava pozitivan broj, a znakovni bit jedan negativni broj. Mantisa se uvijek tumači kao pozitivan broj dva. To nije broj s dvije dopune. Ako je znakovni bit jedan, vrijednost s pomičnim zarezom je negativna, ali mantisa se i dalje tumači kao pozitivan broj koji se mora pomnožiti s -1.

Polje eksponenta tumači se na jedan od tri načina. Eksponent svih ukazuje na to da broj s pomičnom zarezom ima jednu od posebnih vrijednosti plus ili minus beskonačnosti, ili "nije broj" (NaN). NaN je rezultat određenih operacija, poput podjele nule s nulom. Eksponent svih nula ukazuje na denormalizirani broj s pomičnom zarezom. Bilo koji drugi eksponent označava normalizirani broj s pomičnom zarezom.

Mantisa sadrži jedan dodatni djelić preciznosti izvan onih koji se pojavljuju u bicima mantise. Mantisa plovka, koja zauzima samo 23 bita, ima 24 bita preciznosti. Mantisa dvojnika, koja zauzima 52 bita, ima 53 bita preciznosti. Najznačajniji bit mantise je predvidljiv i stoga nije uključen jer eksponent brojeva s pomičnom zarezom u JVM-u pokazuje je li broj normaliziran ili ne. Ako su eksponent sve nule, broj s pomičnom zarezom denormaliziran je, a poznato je da je najznačajniji bit mantise nula. Inače, broj s pomičnom zarezom je normaliziran i poznato je da je najznačajniji dio mantisse jedan.

JVM ne izuzima iznimke kao rezultat bilo kakvih operacija s pomičnom zarezom. Posebne vrijednosti, poput pozitivne i negativne beskonačnosti ili NaN, vraćaju se kao rezultat sumnjivih operacija poput dijeljenja s nulom. Eksponent svih jedinica označava posebnu vrijednost s pomičnim zarezom. Eksponent svih onih s mantisom čiji su bitovi nula označava beskonačnost. Znak beskonačnosti označen je znakovnim bitom. Eksponent svih s bilo kojom drugom mantisom tumači se kao "ne broj" (NaN). JVM uvijek proizvodi istu mantisu za NaN, što su sve nule, osim najznačajnijeg bita mantise koji se pojavljuje u broju. Ove su vrijednosti prikazane za plutajuću dolje:

Posebne plutajuće vrijednosti
Vrijednost Float bitovi (eksponent znaka mantissa)
+ Beskonačnost 0 11111111 00000000000000000000000
-Beskonačnost 1 11111111 00000000000000000000000
NaN 1 11111111 10000000000000000000000

Eksponenti koji nisu niti jedan niti sve nule ukazuju na snagu dvojke pomoću kojih se umnožava normalizirana mantisa. Snaga dvojke može se odrediti tumačenjem eksponentnih bitova kao pozitivnog broja, a zatim od pozitivnog broja oduzimajući pristranost. Za float, pristranost je 126. Za double, pristranost je 1023. Na primjer, eksponentno polje u float-u 00000001 daje snagu dvije oduzimanjem pristranosti (126) od eksponentnog polja protumačenog kao pozitivan cijeli broj (1). Moć dvoje je, dakle, 1 - 126, što je -125. Ovo je najmanja moguća snaga dva za plovak. U drugoj krajnosti, eksponentno polje 11111110 daje snagu dva od (254 - 126) ili 128. Broj 128 je najveća snaga od dva koja su dostupna plovku. Nekoliko primjera normaliziranih plovaka prikazano je u sljedećoj tablici:

Normalizirane plutajuće vrijednosti
Vrijednost Float bitovi (eksponent znaka mantissa) Nepristrani eksponent
Najveći pozitivni (konačni) plovak 0 11111110 11111111111111111111111 128
Najveći negativni (konačni) plovak 1 11111110 11111111111111111111111 128
Najmanji normalizirani plovak 1 00000001 00000000000000000000000 -125
Pi 0 10000000 10010010000111111011011 2

Eksponent svih nula ukazuje da je mantisa denormalizirana, što znači da je nestatirani vodeći bit nula umjesto jedan. Snaga dvojke u ovom je slučaju jednaka najmanjoj snazi ​​dvije koja je dostupna normaliziranoj mantisi. Za plovak je ovo -125. To znači da normalizirane mantike pomnožene s dvije podignute u moć -125 imaju eksponentno polje 00000001, dok denormalizirane mantise pomnožene s dvije podignute u potenciju -125 imaju eksponentno polje 00000000. Dopuštenje za denormalizirane brojeve na dnu kraj raspona eksponenata podržava postupno preljevanje. Ako se umjesto toga koristi najniži eksponent za predstavljanje normaliziranog broja, kod većih brojeva dogodio bi se preliv do nule. Drugim riječima, ostavljanje najnižeg eksponenta za denormalizirane brojeve omogućuje predstavljanje manjih brojeva.Manji denormalizirani brojevi imaju manje bitova preciznosti od normaliziranih brojeva, ali to je poželjno da se premali na nulu čim eksponent dosegne svoju minimalnu normaliziranu vrijednost.

Denormalizirane plutajuće vrijednosti
Vrijednost Float bitovi (eksponent znaka mantissa)
Najmanji pozitivan (ne-nula) plutajući 0 00000000 00000000000000000000001
Najmanji negativni (ne-nulti) plutajući 1 00000000 00000000000000000000001
Najveći denormalizirani plovak 1 00000000 11111111111111111111111
Pozitivna nula 0 00000000 00000000000000000000000
Negativna nula 1 00000000 00000000000000000000000

Izloženi plovak

Java plutajući otkriva svoju unutarnju prirodu Aplet u nastavku omogućuje vam igranje s formatom plutajuće točke. Vrijednost plutajućeg slova prikazuje se u nekoliko formata. Format dva znanstvena zapisa radix prikazuje mantisu i eksponent u bazi deset. Prije prikaza stvarna se mantisa pomnoži s 2 24, što daje integralni broj, a nepristrani eksponent se smanjuje za 24. I integralna mantisa i eksponent se zatim lako pretvaraju u bazu deset i prikazuju.