First of all - 1.18
is not exactly representable in double
. Mathematically the result of:
double odds = 1.18;
is 1.17999999999999993782751062099
(according to an online calculator).
So, mathematically, odds * st
is 1179999999.99999993782751062099
.
But in C++, odds * st
is an expression with type double
. So your compiler has two options for implementing this:
- Do the computation in
double
precision
- Do the computation in higher precision and then round the result to
double
Apparently, doing the computation in double
precision in IEEE754 results in exactly 1180000000
.
However, doing it in long double
precision produces something more like 1179999999.99999993782751062099
Converting this to double
is now implementation-defined as to whether it selects the next-highest or next-lowest value, but I believe it is typical for the next-lowest to be selected.
Then converting this next-lowest result to integer will truncate the fractional part.
There is an interesting blog post here where the author describes the behaviour of GCC:
- It uses long double intermediate precision for x86 code (due to the x87 FPUs long double registers)
- It uses actual types for x64 code (because the SSE/SSE2 FPU supports this more naturally)
According to the C++11 standard you should be able to inspect which intermediate precision is being used by outputting FLT_EVAL_METHOD
from <cfloat>
. 0
would mean actual values, 2
would mean long double is being used.