c++ floating point precision loss: 3015/0.00025298219406977296
- by SigTerm
The problem.
Microsoft Visual C++ 2005 compiler, 32bit windows xp sp3, amd 64 x2 cpu.
Code:
double a = 3015.0;
double b = 0.00025298219406977296;
//*((unsigned __int64*)(&a)) == 0x40a78e0000000000
//*((unsigned __int64*)(&b)) == 0x3f30945640000000
double f = a/b;//3015/0.00025298219406977296;
the result of calculation (i.e. "f") is 11917835.000000000 (*((unsigned __int64*)(&f)) == 0x4166bb4160000000) although it should be 11917834.814763514 (i.e. *((unsigned __int64*)(&f)) == 0x4166bb415a128aef).
I.e. fractional part is lost.
Unfortunately, I need fractional part to be correct.
Questions:
1) Why does this happen?
2) How can I fix the problem?
Additional info:
0) The result is taken directly from "watch" window (it wasn't printed, and I didn't forget to set printing precision). I also provided hex dump of floating point variable, so I'm absolutely sure about calculation result.
1) The disassembly of f = a/b is:
fld qword ptr [a]
fdiv qword ptr [b]
fstp qword ptr [f]
2) f = 3015/0.00025298219406977296; yields correct result (f == 11917834.814763514 , *((unsigned __int64*)(&f)) == 0x4166bb415a128aef ), but it looks like in this case result is simply calculated during compile-time:
fld qword ptr [__real@4166bb415a128aef (828EA0h)]
fstp qword ptr [f]
So, how can I fix this problem?
P.S. I've found a temporary workaround (i need only fractional part of division, so I simply use f = fmod(a/b)/b at the moment), but I still would like to know how to fix this problem properly - double precision is supposed to be 16 decimal digits, so such calculation isn't supposed to cause problems.