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
101
1
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
434
1c37937e0803e
Matlabs
resultat.