Search code examples
cfloating-pointieee-754

Converting floating point to unsigned int while preserving order


I have found a lot of answers on SO focusing on converting float to int.

I am manipulating only positive floating point values. One simple method I have been using is this:

unsigned int float2ui(float arg0) {
    float f = arg0;
    unsigned int r = *(unsigned int*)&f;
    return r;
}

The above code works well yet it fails to preserve the numeric order. By order I mean this:

  float f1 ...;
  float f2 ...;
  assert( ( (f1 >= f2) && (float2ui(f1) >= float2ui(f2)) ) ||
          ( (f1 <  f2) && (float2ui(f1) < vfloat2ui(f2)) ));

I have tried to use unions with the same results. Any idea? I use Homebrew gcc 5.3.0.


Solution

  • The code you're using, as writen, has undefind behavior. If you want to access the representation of floats semi-portably (implementation-defined, well-defined assuming IEEE 754 and that float and integer endianness match), you should do:

    uint32_t float2ui(float f){
        uint32_t r;
        memcpy(&r, &f, sizeof r);
        return r;
    }
    

    For non-negative values, this mapping between floating point values and representation is order-preserving. If you think you're seeing it fail to preserve order, we'll need to see exactly what values you think are a counterexample.