如何仅使用整数运算生成IEEE 754单精度浮点数?

时间:2015-06-11 15:09:31

标签: c ieee-754

假设一个低端微处理器没有浮点运算,我需要生成一个IEE754单精度浮点格式数来推送到文件。

我需要编写一个函数,它将三个整数作为符号,整数和分数,并返回一个字节数组,其中4个字节是IEEE 754单精度表示。

类似的东西:

// Convert 75.65 to 4 byte IEEE 754 single precision representation
char* float = convert(0, 75, 65);

有人有指针或示例C代码吗?我特别难以理解如何转换尾数。

5 个答案:

答案 0 :(得分:1)

您需要生成符号(1位),指数(8位,偏置幂2)和分数/尾数(23位)。

请记住,该分数具有隐含的前导' 1'位,这意味着最重要的领先' 1' bit(2 ^ 22)未以IEEE格式存储。例如,给定一小部分0x755555(24位),存储的实际位将为0x355555(23位)。

还要记住,分数是移位的,这样二进制点就在隐式前导的右边,即1'位。因此IEEE 11位的11 0101 0101 ...代表24位二进制分数1.11 0101 0101 ...... 这意味着必须相应地调整指数。

答案 1 :(得分:0)

值是否必须写成大端或小端?反转位排序?

如果您有空,您应该考虑将该值写为字符串文字。这样你就可以轻松转换整数:只需编写int部分并将“e0”写为指数(或省略指数并写“.0”)。

对于二进制表示,您应该查看Wikipedia。最好是首先将位域组装为uint32_t - 结构在链接文章中给出。请注意,如果整数值超过23位,则可能必须舍入。请记住规范化生成的值。

第二步是将uint32_t序列化为uint8_t - 数组。记住结果的结束!

如果您真的想要8位值,请注意使用uint8_t作为结果;你应该使用无符号类型。对于中间表示,建议使用uint32_t,因为这将保证您对32位值进行操作。

答案 2 :(得分:0)

你没有去过,所以没有放弃。

请记住,您可以将两个32位整数视为一个& b被解释为十进制a.b为单个64位整数,指数为2 ^ -32(其中^为指数)。

所以没有做任何事情你就得到了以下形式:

s * m * 2^e

唯一的问题是你的尾数太长而你的号码没有标准化。

通过可能的舍入步骤进行一些移位和加/减,你就完成了。

答案 3 :(得分:0)

基本前提是:

  1. 鉴于binary32 float
  2. 形成合并的whole和派系部分hundredths的二进制定点表示。此代码使用分别编码整数和百分之一字段的结构。重要的是whole字段至少为32位。
  3. 左移/右移(* 2和/ 2),直到MSbit处于隐含位位置,同时计算移位。一个强大的解决方案还会注意到非零位移出。
  4. 形成有偏见的指数。
  5. 圆形尾数和下降隐含位。
  6. 表格标志(此处未完成)。
  7. 结合以上3个步骤形成答案。
  8. As Sub-normals,infinites&输入whole, hundredths时不会产生非数字,因此不会生成float个特殊情况。
  9. #include <assert.h>
    #include <stdint.h>
    #define IMPLIED_BIT 0x00800000L
    
    typedef struct {
      int_least32_t whole;
      int hundreth;
    } x_xx;
    
    int_least32_t covert(int whole, int hundreth) {
      assert(whole >= 0 && hundreth >= 0 && hundreth < 100);
      if (whole == 0 && hundreth == 0) return 0;
      x_xx x = { whole, hundreth };
      int_least32_t expo = 0;
      int sticky_bit = 0; // Note any 1 bits shifted out
      while (x.whole >= IMPLIED_BIT * 2) {
        expo++;
        sticky_bit |= x.hundreth % 2;
        x.hundreth /= 2;
        x.hundreth += (x.whole % 2)*(100/2);
        x.whole /= 2;
      }
      while (x.whole < IMPLIED_BIT) {
        expo--;
        x.hundreth *= 2;
        x.whole *= 2;
        x.whole += x.hundreth / 100;
        x.hundreth %= 100;
      }
      int32_t mantissa = x.whole;
      // Round to nearest - ties to even
      if (x.hundreth >= 100/2 && (x.hundreth > 100/2 || x.whole%2 || sticky_bit)) {
        mantissa++;
      }
      if (mantissa >= (IMPLIED_BIT * 2)) {
        mantissa /= 2;
        expo++;
      }
      mantissa &= ~IMPLIED_BIT;  // Toss MSbit as it is implied in final
      expo += 24 + 126; // Bias: 24 bits + binary32 bias
      expo <<= 23; // Offset
      return expo | mantissa;
    }
    
    void test_covert(int whole, int hundreths) {
      union {
        uint32_t u32;
        float f;
      } u;
      u.u32 = covert(whole, hundreths);
      volatile float best = whole + hundreths / 100.0;
      printf("%10d.%02d --> %15.6e %15.6e Same:%d\n", whole, hundreths, u.f, best,
          best == u.f);
    }
    
    #include <limits.h>
    int main(void) {
      test_covert(75, 65);
      test_covert(0, 1);
      test_covert(INT_MAX, 99);
      return 0;
    
    }
    

    输出

            75.65 -->    7.565000e+01    7.565000e+01 Same:1
             0.01 -->    1.000000e-02    1.000000e-02 Same:1
    2147483647.99 -->    2.147484e+09    2.147484e+09 Same:1
    

    已知问题:未应用签名。

答案 4 :(得分:0)