Note also the reason 16777221 is rounded down, but 16777223 is rounded up: IEEE floating point, in "round to nearest" mode (likely the default here), rounds values exactly in-between two representable values to the nearest number whose least-significant mantissa bit is 0. This is done in order to avoid the statistical bias of, for example, always rounding such values up (as we are taught in elementary school).
Since at this magnitude, the least-significant mantissa bit falls in the 2s place, odd numbers fall exactly between two valid representations, and are therefore rounded to multiples of 4.
Using the "float" or "double" data types could lead to unexpected results if done without enough precautions. For example incrementing a "float" variable could leave the value unchanged, for relatively small values — like 20 millions. Do you think that these dangers are well understood by the average software developer?
Since at this magnitude, the least-significant mantissa bit falls in the 2s place, odd numbers fall exactly between two valid representations, and are therefore rounded to multiples of 4.