Reella tal i binär form måste lagras på ett speciellt sätt i en dator. Datorer representerar tal som binära heltal (hela tal som är potenser av två), så det finns inget direkt sätt för dem att representera icke-integrala tal som decimaltal eftersom det inte finns någon radixpunkt. Ett sätt för datorer att kringgå detta problem är att representera tal i ett så kallat flytande-punktsformat, där begreppet ”flytande” hänvisar till att radixpunkten kan flyttas (skjutas) genom att talet multipliceras med en exponent (potens).
Grundläggande struktur
Ett binärt flyttal består i praktiken av tre delar:
- Teckenbit (sign): anger om talet är positivt eller negativt.
- Exponent: bestämmer skalningen (hur långt radixpunkten flyttas).
- Signifikand (mantissa eller betydande): innehåller de viktiga siffrorna i talet.
För normaliserade tal i ett vanligt flytande-punktsformat ges värdet av formeln
värde = (-1)^sign · 1.fraction · 2^(exponent − bias)
där 1.fraction betyder att det finns en implicit ledande etta i normaliserad form och bias är en förskjutning (offset) som lagras för att kunna representera både positiva och negativa exponenter som osignerade heltal.
IEEE 754 och vanliga format
Den dominerande standarden för flyttal är IEEE 754. De vanligaste formaten är:
- Single precision (32 bitar): 1 bit tecken, 8 bitar exponent, 23 bitar fraction. Bias = 127.
- Double precision (64 bitar): 1 bit tecken, 11 bitar exponent, 52 bitar fraction. Bias = 1023.
Specialfall i IEEE 754:
- Exponent alla nollor: representerar noll (om fraction = 0) eller subnormala (denormaliserade) tal (om fraction ≠ 0). Subnormala tal saknar den implicita ledande ettan och används för att representera mycket små tal nära noll.
- Exponent alla ettor: representerar oändlighet (om fraction = 0) eller NaN (Not a Number) om fraction ≠ 0.
Varför vissa decimaltal inte kan representeras exakt
Binär representation kan endast exakt uttrycka rationella tal vars nämnare är en potens av två. Ett tal som 0,5 (1/2) är enkelt, men många decimaltal som 0,1 (1/10) har ingen ändlig binär representation — i binärt blir 0,1 ett periodiskt (repetitivt) binärt bråktal 0.0001100110011… och måste avrundas när det lagras i ett ändligt antal bitar. Det leder till små fel i värdet.
Numeriska egenskaper och problem
- Rundningsfel: Eftersom endast ett ändligt antal bitar lagras måste tal ofta avrundas. IEEE 754 specificerar flera avrundningslägen (vanligast är "round to nearest, ties to even").
- Maskinprecision (machine epsilon): det minsta relativa steget mellan tal nära 1. För double är detta ungefär 2^(-52) ≈ 2.22e-16.
- Klyvning och avstängning: När man adderar tal med mycket olika storlek kan de små talen försvinna (de blir för små för att påverka de stora talen inom den givna precisionen).
- Katastrofal avkylning (cancellation): Subtraktion av nästan lika stora tal kan ge stort relativt fel eftersom signifikanta siffror tas bort.
- Ej reflexiv jämförelse: Till synes lika beräkningar kan ge olika binära resultat; därför är direkta likhetskontroller (==) ofta opålitliga för flyttal.
Exempel
Exempelvis lagrar en dator ofta 0,1 som ett tal som är mycket nära men inte exakt 0,1. När man summerar 0,1 flera gånger kan man därför få ett resultat som ser oväntat ut (t.ex. 0,30000000000000004 i stället för 0,3 i dubbel precision).
Praktiska råd för programmerare
- Använd decimal-/BigDecimal-typer eller liknande när exakt decimalrepresentation krävs (t.ex. för pengar).
- Jämför flyttal med en tolerans (epsilon) i stället för med == när du vill avgöra om två värden är "lika".
- Vid summering av många tal med varierande storlek kan algoritmer som Kahan summation reducera ackumulerade rundningsfel.
- Vid behov av hög precision använd multiprecisionbibliotek (t.ex. MPFR, GMP, språkens inbyggda stora tal-klasser).
- Var medveten om specialvärden (NaN, +Inf, −Inf) och hur de beter sig i jämförelser och beräkningar.
Sammanfattning
Binär flytande-punktslagring är en kompromiss mellan räckvidd och precision. Den gör det möjligt att representera mycket stora och mycket små tal i en begränsad mängd bitar, men innebär också rundningsfel, specialfall och numeriska fallgropar. För kritiska tillämpningar gäller det att känna till formaten (t.ex. IEEE 754), förstå dess begränsningar och använda lämpliga tekniker och datatyper beroende på problemet.