cfloating-pointbit-manipulationunsignedieee

Compare 2 floats by their bitwise representation in C


I had this question on my exam, and I couldn't realy solve it, will appreciate some help.

Fill the blanks only, function must return true if and only if x<y. Assume x,y cannot be NaN (but can be +-inf) no casting is allowed, use only ux, uy, sx, sy

bool func(float x, float y) {
    unsigned* uxp = ______________ ;
    unsigned* uyp = ______________ ;
    unsigned  ux  = *uxp;
    unsigned  uy  = *uyp;
    unsigned  sx = (ux>>31); 
    unsigned  sy = (uy>>31);
    return ___________________________;
}

Solution

  • Presumably the assignment assumes float uses IEEE-754 binary32 and unsigned is 32 bits.

    It is not proper to alias float objects with an unsigned type, although some C implementations support it. Instead, you can create a compound literal union, initialize its float member with the float value, and access its unsigned member. (This is supported by the C standard but not by C++.)

    After that, it is simply a matter of dividing the comparison into cases depending on the sign bits:

    #include <stdbool.h>
    
    bool func(float x, float y) {
        unsigned* uxp = & (union { float f; unsigned u; }) {x} .u;
        unsigned* uyp = & (union { float f; unsigned u; }) {y} .u;
        unsigned  ux  = *uxp;
        unsigned  uy  = *uyp;
        unsigned  sx = (ux>>31); 
        unsigned  sy = (uy>>31);
        return
             sx &&  sy ? uy < ux :  // Negative values are in "reverse" order.
             sx && !sy ? (uy | ux) & 0x7fffffffu : // Negative x is always less than positive y except for x = -0 and y = +0.
            !sx &&  sy ?    0    :  // Positive x is never less than negative y.
                         ux < uy ;  // Positive values are in "normal" order.
    }
    
    
    #include <stdio.h>
    
    
    int main(void)
    {
        // Print expected values and function values for comparison.
        printf("1, %d\n", func(+3, +4));
        printf("1, %d\n", func(-3, +4));
        printf("0, %d\n", func(+3, -4));
        printf("0, %d\n", func(-3, -4));
        printf("0, %d\n", func(+4, +3));
        printf("1, %d\n", func(-4, +3));
        printf("0, %d\n", func(+4, -3));
        printf("1, %d\n", func(-4, -3));
    }
    

    Sample output:

    1, 1
    1, 1
    0, 0
    0, 0
    0, 0
    1, 1
    0, 0
    1, 1