c++ - IBM 单精度 float 据转换为预期值

标签 c++ byte bit

我需要从二进制文件中读取值。数据格式为 IBM 单精度 float (4 字节十六进制指数数据)。我有 C++ 代码从文件中读取并取出每个字节并像这样存储它

 unsigned char buf[BUF_LEN];

        for (long position = 0; position < fileLength; position += BUF_LEN) {
            file.read((char* )(&buf[0]), BUF_LEN);

           // printf("\n%8ld:  ", pos);

            for (int byte = 0; byte < BUF_LEN; byte++) {
               // printf(" 0x%-2x", buf[byte]);
            }
        }

这会打印出每个字节的十六进制值。

这张图指定IBM单精度 float IBM single precision floating point

如何将缓冲区转换为浮点值?

最佳答案

格式实际上非常简单,与 IEEE 754 binary32 格式没有特别不同(它实际上更简单,不支持任何“魔术”NaN/Inf 值,并且没有次正规数,因为这里的尾数有一个隐式0 在左边而不是隐含的 1)。

作为Wikipedia说起来,

The number is represented as the following formula: (−1)sign × 0.significand × 16exponent−64.

如果我们假设您读取的字节在 uint8_t b[4] 中,那么结果值应该类似于:

uint32_t mantissa = (b[1]<<16) | (b[2]<<8) | b[3];
int exponent = (b[0] & 127) - 64;
double ret = mantissa * exp2(-24 + 4*exponent);
if(b[0] & 128) ret *= -1.;

请注意,这里我用 double 计算结果,因为 IEEE 754 float 的范围不足以表示相同大小的 IBM 单精度值 (反之亦然)。另外,请记住,由于端序问题,您可能必须恢复上面代码中的索引。


编辑:@Eric Postpischil 正确地指出,如果您有可用的 C99 或 POSIX 2001,而不是 mantissa * exp2(-24 + 4* exponent) 你应该使用 ldexp(mantissa, -24 + 4*exponent),它应该在不同的实现中更精确(并且可能更快)。

关于c++ - IBM 单精度 float 据转换为预期值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45227913/

相关文章:

java - 我怎样才能在java中连接两个字节?

C 按位逻辑运算难题

c - 将 7 位值转换为字节的最快方法

c++ - 单生产者、多消费者架构

c++ - 终端中光标闪烁的删除,如何?

python - 如何在 Python 3(0x80 及更高版本)中编写 ANSI 兼容字节?

c++ - 是否可以在不定义类的情况下重载 [] 运算符以访问 char 的特定位?

c++ - 整数产生十六进制值错误

c++ - 将结构内的二维数组传递给另一个结构

ruby - 在 Ruby 中从一个字节获取两个半字节