将unsigned int转换为仅使用整数运算的单精度浮点数

时间:2013-03-15 07:17:00

标签: floating-point

这个想法是为了做同样的事情 http://www.h-schmidt.net/FloatConverter/IEEE754.html

例如,如果我插入357,我应该得到0x43b28000

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

return *(float*)&result;
}

但我该怎么做?

Convert ieee 754 float to hex with c - printf

我看到了这一点,但似乎没有任何好的解决方案。

2 个答案:

答案 0 :(得分:3)

首先,如果x为零,则返回零。

接下来找到x中最高阶非零位的索引。称之为i

如果i小于24,则x左移23 - i以获得规范化的有效数字。现在清除第23位以隐藏隐含位,并将位23:30设置为127 + i,这是有偏差的指数。返回结果。

否则,通过x右移i - 23以通过截断获得标准化有效数,并清除隐含位并如上所述设置指数。如果你想要的舍入模式是截断或圆到无穷大,你就完成了。否则,您需要查看从x底部移出的位。如果所需的舍入模式为round-to-plus-infinity,并且设置了这些位中的任何一位,则在结果中添加一个并返回。最后,如果所需的舍入模式为round-to-nearest-ties-even-even(IEEE-754 default),则有三种情况:

  • 尾随位为b0...:返回截断的结果。
  • 尾随位是b1000...:这是一个完全中途的情况。如果我们调用截断结果t,则需要返回t + (t&1);即仅在t为奇数的情况下才进行整理。
  • 尾随位是b1...1...:在截断的结果中添加一个并返回。

答案 1 :(得分:1)

我是这样做的:

已更新

这个处理0,INT_MIN并正确舍入,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);
}