【问题标题】:How can I convert 4 bytes storing an IEEE 754 floating point number to a float value in C?如何将存储 IEEE 754 浮点数的 4 个字节转换为 C 中的浮点值?
【发布时间】:2012-09-03 04:58:37
【问题描述】:

我的程序从文件中读取 4 个字节的 IEEE 754 浮点数。我需要将这些字节可移植地转换为我的 C 编译器浮点类型。换句话说,我的 C 程序需要一个带有原型 float IEEE_754_to_float(uint8_t raw_value[4]) 的函数。

【问题讨论】:

  • 由于字节顺序,不会有 100% 可移植的方式。但我敢打赌,您只需一个简单的union 就可以逃脱惩罚。
  • @Mysticial,我想知道这一点。我知道对于大端整数,有一种 100% 可移植的方式来实现这一点。为什么浮点数应该有所不同?
  • 嗯,首先,你不能移动浮点数。所以你不能仅仅使用浮点运算来逐字节地“构造”一个​​浮点值。
  • @Mysticial,但浮点数只是一个数字的另一个数字的幂,以及一个符号位。是不是可以只做sign_bit * powf(x, y)
  • 可以那样做。如果性能很重要,可能不是最好的主意。 (您还必须检查无穷大和 NaN ...)但另一个问题是输入字节的字节序。所以除了使用预处理器检查字节序然后选择适当的实现之外,我看不到任何其他方法。

标签: c floating-point ieee-754


【解决方案1】:

如果您的实现可以保证正确的字节顺序:

float raw2ieee(uint8_t *raw)
{
    // either
    union {
        uint8_t bytes[4];
        float fp;
    } un;
    memcpy(un.bytes, raw, 4);
    return un.fp;

    // or, as seen in the fast inverse square root:
    return *(float *)raw;
}

【讨论】:

    【解决方案2】:

    如果字节序相同,则如下:

    float f;
    memcpy(&f, raw_value, sizeof f);
    return f;
    

    如果没有,说:

    float f;
    char * p = (char *)&f;
    

    现在根据需要手动填充字节 p[0]...。

    【讨论】:

      【解决方案3】:

      这是一个可移植地将 IEEE_754 数字转换为 C 编译器的浮点值的解决方案。此代码有效,但获取分数值的循环很丑陋,可以做得更好。同样,此代码不处理无穷大等特殊情况,而不是数字。

      float IEEE_754_to_float(const uint8_t raw[4]) {
              int sign = (raw[0] >> 7) ? -1 : 1;
      
              int8_t exponent = (raw[0] << 1) + (raw[1] >> 7) - 126;
      
              uint32_t fraction_bits = ((raw[1] & 0x7F) << 16) + (raw[2] << 8) + raw[3];
      
              float fraction = 0.5f;
              for (uint8_t ii = 0; ii < 24; ++ii)
                      fraction += ldexpf((fraction_bits >> (23 - ii)) & 1, -(ii + 1));
      
              float significand = sign * fraction;
      
              return ldexpf(significand, exponent);
      }
      

      【讨论】:

      • 不需要单独处理每个小数位。只需定义 float fraction = 1&lt;&lt;23 | fraction_bits; 并调整最终 ldexpf 中的指数。 (如果原始指数为零,则省略 1&lt;&lt;23 以处理非规范化)。任何 24 位整数都可以无错误地转换为 IEEE 754 浮点数。 (此外,您的循环包括 ii 为 23 的迭代,这没有效果,因为您的 fraction_bits 的第 23 位是 0。)
      猜你喜欢
      • 2014-10-18
      • 1970-01-01
      • 2023-03-08
      • 2016-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多