Utskiftning

Jag fick en fråga under föreläsning om varför (1e16 + 123) - 1e16 blir just 124 i Matlab. Det beror på avrundning och här följer en detaljerad utredning. Vi kan börja med att visa att 1e16 och 123 båda lagras exakt i Matlab. När jag byter till hexadecimalt format i Matlab får jag följande värden:

>> format hex
>> 1e16
ans =
   4341c37937e08000

>> 123
ans =
   405ec00000000000

>> 1e16 + 123
ans =
   4341c37937e0803e

Låt oss studera 1e16 i detalj. De tre första hexadecimala siffrorna, 434 (= 0100 0011 0100 binärt), utgörs av teckenbit 0, och exponentdel, 434 ( = 100 0011 0100 binärt). För att få korrekt exponent måste vi subtrahera 1023 decimalt (3FF hexadecimalt). För att få den fullständiga mantissan måste vi lägga till den underförstådda ettan, mantissan är alltså 1.1c37937e08000.
Här följer nu en kontrollräkning med unixverktyget bc, där man kan byta in- och utmatningsbas.

% bc                   starta bc
scale = 40             räkna med 40 siffror (annars blir det fel)
ibase = 16             inmatningsbas 16
e = 434 - 3FF          exponentdel minus 3FF (1023 decimalt)
e                      skriv ut decimalt
53

m = 1.1C37937E08000    mantissa (måste använda STORA A, B, ..., F)
m                      här ser vi varför det behövdes större scale
1.1102230246251565404236316680908203125000

t = 2^e * m            det blir exakt
t
10000000000000000      (jag har strukit nollorna efter decimalpunkten)

På motsvarande sätt kan man visa att 123 lagras exakt. Vi bildar nu summan 1e16 + 123 (exakt) i bc och skriver ut den i binär form (jag har strukit några avslutande nollor):

ibase = A              byt till decimal inmatningsbas (A är ju 10 decimalt)
obase = 2              byt till utmatningsbasen två, binär utmatning
q = 10^16 + 123        skriv in uttrycket, spara i q
q

100011100001101111001001101111110000010000000001111011

Nu kan vi se vad som händer. Jag har skrivit talet q nedan men grupperat i grupper om 10 bitar.

1000111000 0110111100 1001101111 1100000100 0000000111 1011
                           bit nummer 54, kan vi ej lagra  ^

Talet består alltså av 54 bitar men vi kan bara lagra 53 i typen double (den markerade, röda, biten kan vi alltså ej lagra). Om den minst signifikanta biten hade varit noll så hade vi klarat oss med 53 bitar, men eftersom biten är 1 så måste vi avrunda. Talet q ligger mellan följande två flyttal (notera att jag får justera talets storleksordning med faktorn 2):

1000111000 0110111100 1001101111 1100000100 0000000111 110 * 2 =  1e16 + 124

1000111000 0110111100 1001101111 1100000100 0000000111 101 * 2 =  1e16 + 122
                minst signifikanta biten (bit nummer 53)  ^

och avrundningsregeln är då att talet skall avrundas så att den minst signifikanta biten blir noll. Det lagrade talet blir alltså 1e16 + 124 varför skillnaden (1e16 + 123) - 1e16 blir 124.

Vi kan se att detta stämmer med Matlabs resultat också (de röda delarna överensstämmer):

% bc
obase = 16
(10^16 + 124) / 2
11C37937E0803E

4341c37937e0803e Matlabs resultat.


Back