Conversion of a decimal to double number in C# results in a difference

Interesting – although I generally don’t trust normal ways of writing out floating point values when you’re interested in the exact results.

Here’s a slightly simpler demonstration, using DoubleConverter.cs which I’ve used a few times before.

using System;

class Test
{
    static void Main()
    {
        decimal dcm1 = 8224055000.0000000000m;
        decimal dcm2 = 8224055000m;
        double dbl1 = (double) dcm1;
        double dbl2 = (double) dcm2;

        Console.WriteLine(DoubleConverter.ToExactString(dbl1));
        Console.WriteLine(DoubleConverter.ToExactString(dbl2));
    }
}

Results:

8224055000.00000095367431640625
8224055000

Now the question is why the original value (8224055000.0000000000) which is an integer – and exactly representable as a double – ends up with extra data in. I strongly suspect it’s due to quirks in the algorithm used to convert from decimal to double, but it’s unfortunate.

It also violates section 6.2.1 of the C# spec:

For a conversion from decimal to float or double, the decimal value is rounded to the
nearest double or float value. While this conversion may lose precision, it never causes
an exception to be thrown.

The “nearest double value” is clearly just 8224055000… so this is a bug IMO. It’s not one I’d expect to get fixed any time soon though. (It gives the same results in .NET 4.0b1 by the way.)

To avoid the bug, you probably want to normalize the decimal value first, effectively “removing” the extra 0s after the decimal point. This is somewhat tricky as it involves 96-bit integer arithmetic – the .NET 4.0 BigInteger class may well make it easier, but that may not be an option for you.

Leave a Comment