Double type has limited accuracy, so it is impossible to distinguish between it 100000000000000000000 and 1000000000000000001. If you declare

`double d1 = 1000000000000000001; double d2 = 1000000000000000000;`

- then `d1`

and `d2`

will be the same number. Proof: http://ideone.com/WqQSAd

The problem is that floating point numbers are not infinitely accurate. For `double`

type, for example, 52 bits are allocated for significant digits (and 11 more bits for exponent), the number inside is stored as if encoded as `CCCCCCC * 2^PPPP`

( `C`

is significant digits, `P`

is power). This means that the numbers that can be represented as a `double`

are arranged with a certain step (which depends on the magnitude of the order): the numbers located “between” representable numbers cannot be expressed exactly with the help of `double`

, and they are automatically rounded to the nearest representable number. An example of such a number is 0.1: it is not expressed in (binary) fraction, and the constant 0.1 inside is stored as approximately

`0.1000000000000000055511151231257827021181583404541015625`

The maximum value that can be added to one so that it does not change is called *machine epsilon* . For type `double`

machine epsilon is obviously 2⁻⁵³, that is, around `1.11e-16`

.

Why obvious? Because for a unit, the significant bits are: 10,000,000 ... 000, which means that the next largest number, which can be expressed in `double`

type, must have significant digits 10,000,000 ... 001. (In fact, a little more complicated: the lead unit is not stored, but is implied.)

From this it follows that `1 + 1e-16`

for the `double`

type is indistinguishable from 1. As the order increases for larger numbers, as the first term increases, the machine epsilon increases approximately proportionally. Accordingly, `1e16 + 1`

will be equal to `1e16`

. In your case, you are two orders of magnitude higher than the limit: you add to `1e18`

.

Let's experiment further: http://ideone.com/4XJxFj

`1 + 1.110223024625156e-16 == 1`

but already

`1 + 1.110223024625157e-16 != 1`

This is because `1.110223024625156e-16`

is an approximation to 2⁻⁵³.

Some more information about floating point numbers:

If you need to represent numbers with high accuracy, even the type of `long double`

may not be enough. In this case, you may have to use numbers of *infinite precision* . Such numbers are embedded in some languages (for example, Java and C #), and for C and C ++ there are good libraries that provide such numbers. I would recommend GMP .