Web Log di Adrian Florea

"You know you've achieved perfection in design, not when you have nothing more to add, but when you have nothing more to take away." Antoine de Saint-Exupery
posts - 440, comments - 2715, trackbacks - 3944

My Links

Archives

Post Categories

Image Galleries

.RO Blogs

.RO People

.RO Sites

Blogs

Furls

Links

vinCitori

Double Inside

Da uno scambio di messaggi questi giorni sul Messenger con M.rkino e Gianluca, sono usciti fuori alcuni aspetti della System.Double, a prima vista strani. Per esempio, questo di seguito, presentato da Brian Grunkemeyer in SLAR (p. 156):

"You might wonder why this simple code would throw an OverflowException:

string s = Double.MaxValue.ToString();
double d = Convert.ToDouble(s);

The Convert.ToDouble() method throws an exception due to rounding errors. Note that the IEEE spec for doubles says that a double has about 15.7 decimal digits worth of precision, but to accurately represent that number you need to print out 17 digits to avoid rounding errors."

Lo standard a cui fa riferimento è lo "ANSI/IEEE 754-1985: IEEE Standard for Binary Floating-Point Arithmetic". In sostanza, la rappresentazione su 64 bit di un double D descritta dallo standard, identifica il primo bit (S) come il bit di segno, i prossimi 11 come i bit dell'esponente (E) e gli ultimi 52 come i bit della parte frazionaria (F). Il valore D del double risulta allora in base a questa tabella:

S E F D
* 2047 F>0 System.Double.NaN
1 2047 0 System.Double.NegativeInfinity
0 2047 0 System.Double.PositiveInfinity
S 0<E<2047 < TD> F Pow(-1,S)*Pow(2,E-1023)*(1.F)
S 0 F > 0 Pow(-1,S)*Pow(2,-1022)*(0.F)
1 0 0 -0
0 0 0 0

Proviamo adesso a vedere la rappresentazione di System.Double.MaxValue (1.79769313486232E+308)? :-)
E' un numero positivo, quindi: S = 0.
Per vedere quanto è la parte E, si risolve:
Pow(10, 308) = Pow(2, x)
e si ottiene subito:
x = 308 * Log(10, 2) = 1023.15...
Risulta E = 2046.
Rimane da calcolare F :-) Abbiamo:
Pow(-1, 0) * Pow(2, 2046-1023) * (1.F) = MaxValue
cioè:
(1.F) = MaxValue * Pow(2, -1023).
Ma,
MaxValue * Pow(2, -1023) = 2
e quindi dobbiamo risolvere:
(1.F) = 2
cioè:
(0.F) = 1 OVERFLOW!!!

Quod Erat Demonstrandum :-)

Print | posted on venerdì 21 maggio 2004 01:58 | Filed Under [ Carillon .NET ]

Powered by:
Powered By Subtext Powered By ASP.NET