user2054534
user2054534

Reputation: 181

convert unsigned int to single precision floating point with only integer operations

The idea is for this to do pretty much the same thing as this http://www.h-schmidt.net/FloatConverter/IEEE754.html

For example if i plug in 357, i should get 0x43b28000

float unsignedToFloat( unsigned int x ) {
unsigned int result = 0;

return *(float*)&result;
}

but how do I do this?

Convert ieee 754 float to hex with c - printf

I saw this, but there didn't seem to be any good solutions.

Upvotes: 0

Views: 2258

Answers (2)

Rudy Velthuis
Rudy Velthuis

Reputation: 28806

I did it this way:

UPDATED

This one handles 0, INT_MIN and rounding correctly, AFAICT:

#define SIGN_MASK       (1 << 31)
#define HIDDEN_MASK     (1 << 23)
#define MANTISSA_MASK   (HIDDEN_MASK - 1)

#define INT_MIN 0x80000000
#define INT_MAX 0x7FFFFFFF

float intToFloat(int n)
{
    int sign;
    int exp;
    unsigned int half;

    if (n == 0)
         return 0.0f;

    if (n == INT_MIN)
        return -(float)(INT_MIN);

    sign = n < 0 ? SIGN_MASK : 0;
    if (sign)
        n = -n;

    if (!(n & ~(HIDDEN_MASK | MANTISSA_MASK)))
        for (exp = 0; !(n & HIDDEN_MASK); n <<= 1, exp--) ;
    else
    {
        half = 0;
        for (exp = 0; n & ~(HIDDEN_MASK | MANTISSA_MASK); exp++)
        {
            half >>= 1;
            if (n & 1)
                half |= 0x80000000;
            n >>= 1;
        }
        if (half > INT_MIN || ((half == INT_MIN) && (n & 1) != 0))
        {
            n++;
            if (n == 0x1000000)
            {
                n = 0; // or 0x800000, doesn't matter.
                exp++;
            }
        }

    }

    exp = (exp + 127 + 23) << 23;
    n = (n & MANTISSA_MASK) | sign | exp;

    return *((float *)&n);
}

Upvotes: 1

Stephen Canon
Stephen Canon

Reputation: 106197

First, if x is zero, return zero.

Next find the index of the highest-order non-zero bit in x. Call it i.

If i is less than 24, left-shift x by 23 - i to get a normalized significand. Now clear bit 23 to hide the implicit bit, and set bits 23:30 to 127 + i, which is the biased exponent. Return the result.

Otherwise, right-shift x by i - 23 to get a normalized significand via truncation, and clear the implicit bit and set the exponent as above. If your desired rounding mode is truncation or round-to-minus-infinity, you are done. Otherwise, you will need to look at the bits that were shifted off the bottom of x. If the desired rounding mode is round-to-plus-infinity and any of those bits are set, add one to the result and return. Finally, if the desired rounding mode is round-to-nearest-ties-to-even (IEEE-754 default), there are three cases:

  • the trailing bits are b0...: return the truncated result.
  • the trailing bits are b1000...: this is an exact halfway case. If we call the truncated result t, you need to return t + (t&1); i.e. round up only if t is odd.
  • the trailing bits are b1...1...: add one to the truncated result and return.

Upvotes: 3

Related Questions