floating point cannot do that, its precision is based on powers of 2 (1/2, 1/4, 1/8, and so on). For small values (in the range 0-1), there are _so many_ values represented that the powers of 2 map pretty tightly to the powers of 10. But as you repeat calculations, or get into larger values (say, in the range 1,000,000 - 1,000,001), the floating points become more sparse and errors crop up even easier.
For example, using 32 bit floating point values, each consecutive floating point in the range 1,000,000 - 1,000,001 is 0.0625 away from the next.
jshell> Math.ulp((float)1_000_000)
$5 ==> 0.0625