The result of the following multiplication doesn't have decimals.
Maybe it doesn't in base 10 (decimal), but computers don't work in base 10. They work in base 2, and in base 2 128.51 has more decimals fractional digits than can be stored in the float
(or, actually, any similar format — it would require infinite places, much like trying to write out 1/3 in decimal).
This error carries through so, although mathematically 64255 is a whole number, the result of your multiplication is closer to 64254.9999999999927240.
std::cout
is automatically rounding this up by default (because it knows that this kind of thing happens); however, during conversion to uint16_t
, a dumb truncation happens instead, resulting in the incorrect 64254.
With some I/O manipulator magic, we can see this more clearly:
#include <iostream>
#include <iomanip>
int main()
{
std::cout << std::fixed << std::setprecision(16) << (500.00 * 128.51) << std::endl;
std::cout << uint16_t(500.00 * 128.51) << std::endl;
}
// 64254.9999999999927240
// 64254