Reputation: 3543
Background: I have some elements in a record, where some elements can be float, unsigned int or unsigned long long. So, I though to use float as a common value to return from a function that reads those elements.
However, I am seeing this strange error on converting from unsigned int to float. On printing the value, it gets changed. How can I avoid it? Should I not return float from this function?
#include <iostream>
#include <limits>
using namespace std;
int main()
{
unsigned int myU = numeric_limits<unsigned int>::max();
cout<<" myU is "<<myU<<'\n'; //correct
float myF = (float) myU;
cout<<" back To Long "<<(unsigned long long ) myF<<'\n'; //error?
cout<<" back To unsigned int "<<(unsigned int ) myF<<'\n'; //error?
cout<<" to Float Without Fixed "<<(float) myU<<'\n';//not clear, so have to use fixed
cout<<" to Float With Fixed "<<fixed<<(float) myU<<'\n';//error?
cout<<" difference "<<myF-myU<<'\n'; //error?
cout<<" myU+32 "<<myU+32<<'\n'; //-1+32=31 ==> understandable
}
Output with gcc 4.6.3:
myU is 4294967295
back To Long 4294967296
back To unsigned int 0
to Float Without Fixed 4.29497e+09
to Float With Fixed 4294967296.000000
difference 1.000000
myU+32 31
Upvotes: 1
Views: 3938
Reputation: 6136
The number 4294967295
in float (32-bit IEEE 754)
is represented as follows:
0 10011111 00000000000000000000000
sign exponent mantissa
(+1) (2^32) (1.0)
The rule for converting it back to an integer (or long in this case) is:
sign * (2^exponent) * mantissa
and the result would be 4294967296
which is in appropriate size to fill long long
for you but too big to be fit in unsigned int
so you will get 0
for unsigned int
conversion.
Note that the problem is the limitation of representing large numbers with float for example 4294967295
and 4294967200
both are representing the same bits when they are stored as floats.
Upvotes: 3
Reputation: 564
The main issue you are seeing, is that a floating point type only provides a limited precision of its fraction part, which of course is natural since it can only hold so much information.
Now when you convert from unsigned int
to float
, the number you are using is too long to fit into the fraction part. Now that some precision was lost and you convert back to an integer format it may differ. To unsigned long long
, the result is just one bigger, but in the conversion to unsigned int
, you see an overflow happpening.
Upvotes: 0