Floating point 将无符号整数转换为仅包含整数运算的单精度浮点

Floating point 将无符号整数转换为仅包含整数运算的单精度浮点,floating-point,Floating Point,这个想法是为了让它和这个做几乎相同的事情 例如,如果我插入357,我应该得到0x43b28000 float unsignedToFloat( unsigned int x ) { unsigned int result = 0; return *(float*)&result; } 但是我该怎么做呢 我看到了这一点,但似乎没有任何好的解决方案。首先,如果x为零,则返回零 接下来在x中查找最高阶非零位的索引。叫它i 如果i小于24,将x左移23-i,以获得标准化的有效位。现在清除

这个想法是为了让它和这个做几乎相同的事情

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

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

return *(float*)&result;
}
但是我该怎么做呢


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

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

接下来在
x
中查找最高阶非零位的索引。叫它
i

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

否则,将
x
右移
i-23
,通过截断获得标准化的有效位,然后清除隐式位并如上所述设置指数。如果您想要的舍入模式是截断或舍入到负无穷大,那么就完成了。否则,您需要查看从
x
底部移位的位。如果所需的舍入模式是舍入到正无穷大,并且设置了这些位中的任何一位,则在结果中添加一位并返回。最后,如果所需的舍入模式是舍入到最接近的偶数(IEEE-754默认值),则有三种情况:

  • 尾随位是
    b0…
    :返回截断的结果
  • 尾随位是
    b1000…
    :这是一个精确的中间情况。如果调用截断的结果
    t
    ,则需要返回
    t+(t&1)
    ;i、 e.仅当
    t
    为奇数时,才进行取整
  • 尾随位是
    b1…1…
    :向截断的结果中添加一位并返回

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

接下来在
x
中查找最高阶非零位的索引。叫它
i

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

否则,将
x
右移
i-23
,通过截断获得标准化的有效位,然后清除隐式位并如上所述设置指数。如果您想要的舍入模式是截断或舍入到负无穷大,那么就完成了。否则,您需要查看从
x
底部移位的位。如果所需的舍入模式是舍入到正无穷大,并且设置了这些位中的任何一位,则在结果中添加一位并返回。最后,如果所需的舍入模式是舍入到最接近的偶数(IEEE-754默认值),则有三种情况:

  • 尾随位是
    b0…
    :返回截断的结果
  • 尾随位是
    b1000…
    :这是一个精确的中间情况。如果调用截断的结果
    t
    ,则需要返回
    t+(t&1)
    ;i、 e.仅当
    t
    为奇数时,才进行取整
  • 尾随位是
    b1…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);
      }
      
      定义符号掩码(1=1; } 如果(一半>整数最小值((一半==整数最小值)和&(n&1)!=0)) { n++; 如果(n==0x1000000) { n=0;//或0x800000,这无关紧要。 exp++; } } } exp=(exp+127+23)我是这样做的:

      更新 这一个正确处理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);
      }
      
      定义符号掩码(1=1; } 如果(一半>整数最小值((一半==整数最小值)和&(n&1)!=0)) { n++; 如果(n==0x1000000) { n=0;//或0x800000,这无关紧要。 exp++; } } }
      Exp=(Exp+127+23)如果你使用C++,你可以使用RealTytRayCask.我不明白.你的函数返回一个浮点.它怎么能返回<代码> 0x43B2800< /代码>?你是说它返回代码> 357?/代码>?(你链接的第一页在底部回答了这个问题,在FAQ中.这个问题毫无意义。这就像问如何将“两个蘑菇”中的“二”转换为“两辆车”中的“二”。没什么可做的。在这种情况下,0x43b28000是二进制(十六进制)表示32位单字节。我没有代码,目前也没有时间,但如果我以后有一点时间,我将描述如何实现它(如果没有其他人这样做)。它只涉及一些移位和一些加法/减法。@roger_rowland:我觉得userXYZ想知道它是如何工作的,而不是让编译器替他做的。@Rudy Velthuis-好吧。我在OP的帖子中跟踪了链接,它描述了Java应用程序是如何工作的,这与“reinterpret_cast”的工作原理完全相同。是吗如果你使用C++,你可以使用RealTytCask.我不明白。你的函数返回一个浮点。它怎么能返回<代码> 0x43B2800< /代码>?你是说它返回代码> 357 < /代码>?(你链接的第一页在底部回答了这个问题,在FAQ中的第二个问题)这个问题毫无意义。这就像问如何将“两个蘑菇”中的“二”转换为“两辆车”中的“二”。没什么可做的。在这种情况下,0x43b28000是二进制(十六进制)表示32位单字节。我没有代码,目前也没有时间,但如果我以后有一点时间,我将描述如何实现它(如果没有其他人这样做)。它只涉及一些移位和一些加法/减法。@roger_rowland:我觉得userXYZ想知道它是如何工作的,而不是让编译器替他做的。@Rudy Velthuis-好吧。我在OP的帖子中找到了链接,它描述了Java应用程序是如何做到的,我也知道了