Ceiling
returns the number passed to it if they are whole numbers, or else the next highest whole number. So 5.0
stays 5.0
but 5.00001
becomes 6.0
.
So, of the examples, the following are obvious:
Math.Ceiling(123.121 * 100) / 100 // Obtain 12312.1, next highest is 12313.0, then divide by 100 is 123.13
Math.Ceiling(123.1200000000001 * 100) / 100 // Likewise
Math.Ceiling(123.12000000000002 * 100) / 100 // Likewise
The more confusing one is:
Math.Ceiling(123.12000000000001 * 100) / 100 //display 123.12
However, let's take a look at:
123.12000000000001 * 100 - 12312.0 // returns 0
Compared to:
123.1200000000001 * 100 - 12312.0 // returns 1.09139364212751E-11
123.12000000000002 * 100 - 12312.0 // returns 1.81898940354586E-12
The latter two multiplications have results that are slightly higher than 12312.0, so while (123.12000000000002 * 100).ToString()
returns "12312"
the actual number produced by 123.12000000000002 * 100
is mathematically 12312.000000000002
the nearest possible double
for 123.12000000000002
is is 123.1200000000000181898940354586
so that is what is worked on.
If you are used to only doing decimal arithmetic it may seem strange that 123.12000000000002
is "rounded" to 123.1200000000000181898940354586
, but remember that these numbers are stored in terms of binary values, and rounding depends on the base you are working in.
So while the string representation doesn't indicate it, it is indeed slightly higher than 12312
and so its ceiling is 12313
.
Meanwhile with 123.12000000000001 * 100
, that is mathematically 12312.000000000001
but the nearest possible double
to 123.12000000000001
is that it can fit into is 123.12
. So that is what is used for the multiplication, and when the result passed to the subsequent call to Ceiling()
its result is 12312
.