"René Holdgard Wilhardt" wrote:
> Hej.
>
> Hvis jeg laver denne her:
>
> double d = 4.1;
> double rest = d % 1;
>
> Så ville jeg mene at rest = 0.1
>
> Men jeg får dette resultat:
> 0.09999999999999964
>
> Hvorfor ?
Hermed et forsøg på en lidt mere uddybende forklaring:
% operatoren defineres på følgende måde (kun essensen) i Java Language
Specification:
(
http://java.sun.com/docs/books/jls/first_edition/html/15.doc.html#239829)
"the floating-point remainder r from the
division of a dividend n by a divisor d is defined by the
mathematical relation r = n-d*q where q is an integer [...]
whose magnitude is as large as possible without
exceeding the magnitude of the true mathematical quotient of
n and d."
vi får så (q=4):
4.1 % 1 = 4.1 - 1 * 4 = 4.1 - 4
4.1-4 defineres så til at skulle give et IEEE 754 resultat
(
http://java.sun.com/docs/books/jls/first_edition/html/4.doc.html#9249)
- and the plot thickens:
I IEEE 754 repræsenteres double værdier som 1 fortegnsbit, 11
eksponentbits og 52 'betydende' bits.
Værdien af et flydende tal er så defineret til at være
((-1)^fortegn) * (1+betydende) * (2^(eksponent-1023))
De betydende regnes ud fra venstre mod højre som en sum af
negative 2-potenser. Eks.
101 = 2^-1 + 2^-3,
001 = 2^-3 og
011 = 2^-2 + 2^-3
Hvis vi så i stedet for 52 betydende bits bruger 3, bliver den nærmeste
representation af 0.1 følgende mønster:
sign: eksponent: betydende:
0 01111111011 011
Dette er dog ikke 0.1 men 0.859375, da
((-1)^0)) //fortegn
* (1 + (0*2^-1) + (1*2^-2) + (1*2^-3)) // betydende
* (2^(1019-1023)) // eksponent
= 1 * (1.375) * (0.625)
= 0.859375
0.1 vil altså altid blive representeret som 0.859375 med 3 betydende
bits.
Situationen med 52 betydende bits er den samme - man skal bare fælde en
regnskov for at regne den ud i hånden.
Ulrik Magnusson