Why are the two following result different? The result of the following multiplication should be an integer anyway.
uint16_t test = 500.00 * 128.51;
std::cout << test << std::endl; ----> 64254
but
float test = 500.00 * 128.51;
std::cout << test << std::endl; ----> 64255
(moving from a comment)
To complete the previously linked duplicate, 500.00 * 128.51 is actually slightly smaller than 64255 (as 128.51 cannot be accurately represented in binary FP).
When casting to an integral type, decimals are discarded (the value is truncated), so your 64254.99999... becomes 64254.
OTOH, when keeping it as a double, you preserve the 64254.9999..., and the default ostream::operator<< behavior is to round at some decimal position when printing, so when displaying it you see it just as 64255.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With