I observe a strange behaviour with mingw while performing multiplication of a unit64 variable with float. Is this a problem in the compiler?
Below is my code:
#include <iostream>
using namespace std;
int main() {
uint64_t myvar = 4293057;
float mycrasher = 1000;
myvar = myvar*mycrasher;
cout << "value after mul is "<<myvar << endl;
return 0;
}
The output value displayed is 4293057024 and not 4293057000!!
An IEEE754 single-precision value (such as your
float) has only about seven decimal digits of precision. Beyond that, it’s imprecise. You don’t even have to multiply it by 1000, multiplying it by 10 gives you42930568.You can see what’s happening with the following code:
which outputs the not-so-precise:
In order to explain more fully, IEEE754 floating point values are limited in precision simply because they have a limited number of bits available for that purpose. Single precision values are 32 bits in length and have 23 bits of that for the fraction (the other bits are for sign and exponent). Those 23 bits equate to about seven decimal digits. You can find further analysis here.
The number 42930570 is not able to be represented exactly in a single precision value. You either get the bit pattern
0x4c23c462which is42930568or the next higher0x4c23c463which is42930572.The reason why they’re being converted to
floatinstead ofuint64_tis because that’s what the standard says. In C++03, the “multiplicative operators” section (5.6) says:The usual arithmetic conversions are detailed in section 5, paragraph 9 and consist of:
Since you have a
floatand auint64_t, that’s covered by the third bullet point above. In the “floating-integral conversion” section (4.9), we see:Hence that’s why you’re seeing the loss of precision.
That hasn’t changed in C++11. The wording is changed, and a little more verbose, but the sections still boil down to the same results.