Kako se float čuva
IEEE 754 čuva broj kao znak × 1.razlomak × 2eksponent, u binarnoj naučnoj notaciji. 32-bitni float ima 1 bit znaka, 8 bitova eksponenta i 23 bita razlomka; 64-bitni double ima 1, 11 i 52. Eksponent se čuva sa pomakom (bias, 127 ili 1023) tako da mu nikad ne treba sopstveni bit znaka, a vodeća jedinica mantise se uopšte ne čuva jer je kod normalnih brojeva uvek prisutna.
| Znak | Eksponent | Razlomak | Pomak | Decimalnih cifara | |
|---|---|---|---|---|---|
| float32 (binary32) | 1 | 8 | 23 | 127 | ~7 |
| float64 (binary64) | 1 | 11 | 52 | 1023 | ~16 |
Zašto 0.1 + 0.2 nije 0.3
0.1 nema konačan binarni razvoj, baš kao što ga 1/3 nema u decimalnom sistemu. Najbliži float64 je 0,1000000000000000055511151231257827…, a 0.2 i 0.3 su takođe malo pomereni. Sabiranje dve zaokružene vrednosti i ponovno zaokruživanje završava jednu jedinicu dalje od float broja najbližeg 0.3, pa poređenje ne uspeva. Unesite 0.1 iznad i pogledajte red „tačna sačuvana vrednost“ da biste videli zaokruživanje direktno.
Specijalni obrasci
- Nula: eksponent i razlomak sve nule. Bit znaka i dalje važi, pa −0 postoji i jednak je +0 u poređenjima.
- Subnormalni: eksponent sve nule, razlomak različit od nule. To su sićušne vrednosti ispod normalnog opsega, sa smanjenom preciznošću i bez implicitne vodeće jedinice.
- Beskonačnost: eksponent sve jedinice, razlomak 0. Nastaje prekoračenjem i deljenjem nulom.
- NaN: eksponent sve jedinice, razlomak različit od nule. Nastaje iz 0/0, ∞−∞, sqrt(−1). NaN nije jednak ničemu, uključujući sebe.
Ručno čitanje bitova
- Podelite obrazac na polja znaka, eksponenta i razlomka.
- Oduzmite pomak od eksponenta da dobijete stvarni stepen dvojke.
- Stavite „1.“ ispred bitova razlomka (ili „0.“ za subnormalne) i pomnožite sa 2 na taj stepen.
Za 0x40490FDB: znak 0, eksponent 10000000 = 128 → 128 − 127 = 1, razlomak 1.1001001000011111101101 → 1.5707963 × 2 = 3.1415927, float32 najbliži broju π.
Pitanja
Koja je razlika između float i double?
Float (float32) koristi 32 bita i daje oko 7 značajnih decimalnih cifara; double (float64) koristi 64 bita i daje oko 16. Double je podrazumevani u većini jezika (JavaScript brojevi, Python float, C double); float se koristi tamo gde su memorija ili propusni opseg GPU-a bitni.
Zašto eksponent koristi pomak umesto dvojičnog komplementa?
Sa pomakom se float brojevi istog znaka ispravno porede kao obični celi brojevi: veći obrazac bitova je veći broj. To čini sortiranje i poređenje jeftinim u hardveru.
Šta je mašinski epsilon?
Razmak između 1.0 i sledećeg predstavljivog float broja: 2⁻²³ ≈ 1,19 × 10⁻⁷ za float32 i 2⁻⁵² ≈ 2,22 × 10⁻¹⁶ za float64. Razmak raste sa veličinom broja: na 2²⁴ float32 više ne može da predstavi neparne cele brojeve.
Koji je najveći ceo broj koji double može tačno da sačuva?
2⁵³ = 9.007.199.254.740.992. Iznad toga nisu svi uzastopni celi brojevi predstavljivi, zbog čega JavaScript ima Number.MAX_SAFE_INTEGER (2⁵³ − 1) i BigInt.
Zašto moj jezik ispisuje 0.30000000000000004?
Zato što je to najkraći decimalni zapis koji jednoznačno identifikuje double koji ste dobili iz 0.1 + 0.2. Ispis je ispravan; sačuvana vrednost je ono što se razlikuje od 0.3.