Reputation: 51
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
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
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
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