Why you can't Double.Parse(Double.MaxValue.ToString()) or System.OverloadExceptions when using Double.Parse
This was an interesting one. A fellow here was returning double.MaxValue in an XML element and was seeing:
System.InvalidOperationException : There is an error in XML document (1, 539).----> System.OverflowException : Value was either too large or too small for a Double.
It seems that while he was sending out Double.MaxValue the system was unable to use Double.Parse() on it. In other words, he wasn't able to "roundtrip" his value, like Double.Parse(Double.MaxValue.ToString()).
The problem stems from there being no 1:1 representation between decimal and floating point numbers. For example, how do you express 2/3? Do you say 0.6666666667? You've rounded up. You can't say 0.66666 with that little bar on the top. So, you either have to round up (creating data) or limit the digits (losing data).
//This will throw a System.OverflowException…
double d1 = double.Parse( "1.79769313486232E+308" );
Change the last digit:
double d2 = double.Parse( "1.79769313486231E+308" );
//This will work.
A few interesting articles I found referenced in Google Groups:INFO: Precision and Accuracy in Floating-Point Calculations: Q125056
INFO: IEEE Floating-Point Representation and MS Languages: Q36068
Using Edge Cases as Magic Numbers is more evil than using Magic Numbers
However, you can use Double.MaxValue.ToString("R") to prefer roundtrips over precision. From the MSDN Help:
The round-trip specifier guarantees that a numeric value converted to a string will be parsed back into the same numeric value. When a numeric value is formatted using this specifier, it is first tested using the general format, with 15 spaces of precision for a Double and 7 spaces of precision for a Single. If the value is successfully parsed back to the same numeric value, it is formatted using the general format specifier. However, if the value is not successfully parsed back to the same numeric value, then the value is formatted using 17 digits of precision for a Double and 9 digits of precision for a Single. Although a precision specifier can be appended to the round-trip format specifier, it is ignored. Round trips are given precedence over precision when using this specifier. This format is supported by floating-point types only.