user984260
user984260

Reputation: 3543

Error on converting from unsigned int to float

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

Answers (2)

Pooya
Pooya

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

Alexander B&#252;se
Alexander B&#252;se

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

Related Questions