user625895
user625895

Reputation: 51

.Net float to double conversion

Can anyone explain why the third output below prints out a value that is 128 from expected value?

I ran the following code with Target framework = .NET Framework 4

CODE:

    static void Main(string[] args)
    {
        float f = 3510000000f;
        double d = 3510000000d;

        Console.WriteLine("f = {0:f1}", f);
        Console.WriteLine("d = {0:f1}", d);
        Console.WriteLine("f converted to a double = {0:f1}",
            Convert.ToDouble(f));
        Console.WriteLine("f converted to a double using strings = {0:f1}",
            Convert.ToDouble(f.ToString()));
    }

Upvotes: 5

Views: 1534

Answers (3)

Sam Saffron
Sam Saffron

Reputation: 131092

To quote Jon Skeet:

It's not that you're actually getting extra precision - it's that the float didn't accurately represent the number you were aiming for originally. The double is representing the original float accurately; toString is showing the "extra" data which was already present.

Convert float to double without losing precision

Upvotes: 0

Joel Rondeau
Joel Rondeau

Reputation: 7586

3510000000f represented in bits is 1101 0001 0011 0110 0101 1001 1000 0000. You have a number with 25 bits of precision, and .Net floats only have 24 bits of precision. Therefore, when converting to a double, you've lost precision. In this case, it rounded up to 1101 0001 0011 0110 0101 1010 0000 0000.

Upvotes: 5

Zooba
Zooba

Reputation: 11438

Basically, it is a rounding error.

In the binary representation of a floating point value, the exponent and the mantissa are separated. What this means is that internally, your number is represented as:

(1.634471118450164794921875) * 2^31

However, the first part of that number is restricted to fitting within 23 bits (Wikipedia on 32-bit floats), so we have to round to the nearest 2^-23:

(1.634471118450164794921875) % (0.00000011920928955078125) = 
 1.6344711780548095703125

So your number is actually:

(1.6344711780548095703125) * 2^31

If we evaluate this, we get 3510000128 rather than 3510000000.

In short, this is the same rounding error that you get when you specify 0.1: neither can be expressed exactly given the limitations of the representation.

Upvotes: 3

Related Questions