C++ IBM单精度浮点数据到预期值的转换

C++ IBM单精度浮点数据到预期值的转换,c++,byte,bit,C++,Byte,Bit,我需要从二进制文件中读取值,数据格式为IBM单精度浮点(4字节十六进制指数数据),并将该值用作十进制数。我有C++代码,从文件中读取并取出每个字节并像一样存储它。 unsigned char buf[BUF_LEN]; for (long position = 0; position < fileLength; position += BUF_LEN) { file.read((char* )(&buf[0]), BUF_LEN);

我需要从二进制文件中读取值,数据格式为IBM单精度浮点(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]);
            }
        }
无符号字符buf[buf_LEN];
对于(长位置=0;位置<文件长度;位置+=BUF_LEN){
read((char*)(&buf[0]),buf_LEN);
//printf(“\n%8ld:”,位置);
用于(int字节=0;字节
这将打印出每个字节的十六进制值

此图指定IBM单精度浮点
我不明白24位正二进制分数是什么。我知道如何在hexdecbinary之间进行转换,因此我的基本理解是将所有的q值作为一个非常长的二进制段,将Q24(2)^(23)作为最大值,同时将前面的所有值相加,然后将数字乘以10^-24。但我的直觉告诉我这是错误的。澄清什么是基点或MSB会有所帮助

该格式实际上非常简单,与IEEE 754 binary32格式没有什么特别的不同(它实际上更简单,不支持任何“神奇的”NaN/Inf值,并且没有低于正常值的数字,因为这里的尾数在左边有一个隐式0,而不是隐式1)

正如它所说

该数字表示为以下公式:(−1) 符号×0.5有效位×16指数−64

如果我们假设您读取的字节位于a
uint8\u 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.;

uint32\u t尾数=(b[1]该格式实际上非常简单,与IEEE 754 binary32格式没有什么特别的区别(它实际上更简单,不支持任何“神奇”NaN/Inf值,也没有低于正常值的数字,因为这里的尾数在左侧有一个隐式0,而不是隐式1)

正如它所说

该数字表示为以下公式:(−1) 符号×0.5有效位×16指数−64

如果我们假设您读取的字节位于a
uint8\u 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.;

uint32\u t尾数=(b[1]示例可用于在下面的链接中将十六进制转换为十进制示例可用于在下面的链接中将十六进制转换为十进制抱歉,您能否解释尾数是什么以及恢复索引的含义?为了清晰起见,我添加的图片基本上正是数据将如何存储在文件中。因此,在ta中ble似乎最重要的位在最右边的列中。因此我相信这意味着它是小endian?因此我必须还原索引。但我不确定这在您的代码中会如何工作。它是否需要另一个围绕位交换的函数。还原索引意味着更改
b[0]
b[3]
b[1]
b[2]
;这应该可以解释字节尾数的差异。它所使用的2^-1是尾数的最高有效位,也就是说,尾数的MSb对应于值2^-1(注意,必须将尾数的24位整数乘以2^-24)。我编写的代码遵循您的图片所示的字节顺序,即big-endian。如果确实如此,我的代码应该按原样工作。此外,不要混淆位顺序和字节顺序;当您处理软件时,字节内的位已经正确排序,您通常只需担心字节顺序。
ldexp(尾数,-24+4*指数)
优于
尾数*exp2(-24+4*指数)
ldexp
就是针对这类情况而设计的,它将有效位和指数组合成浮点值(或通过指数的整数值调整现有值),并且它避免了
exp2
的数值问题。由于
exp2
必须处理非整数参数,因此它使用各种近似实现,并且在某些实现中可能返回不完美的结果。对不起,您能否解释尾数是什么,以及为清晰显示该图片而还原索引的含义我添加的内容基本上就是数据在文件中的存储方式。因此,在表中,最高有效位似乎位于最右边的列中。因此我认为这意味着它是little endian?因此我必须还原索引。但我不确定这在您的代码中会如何工作。是否需要另一个在位之间交换的er函数。恢复索引意味着更改
b[0]
b[3]
b[1]
b[2]
;这应该可以解释字节尾数的差异。它所使用的2^-1是尾数的最高有效位,也就是说,尾数的MSb对应于值2^-1(注意,必须将尾数的24位整数乘以2^-24)。我编写的代码遵循您的图片所示的字节顺序,即big-endian。如果确实如此,我的代码应该按原样工作。此外,不要混淆位顺序和字节顺序;当您处理软件时,字节内的位已经正确排序,您通常只需担心字节顺序。
ldexp(尾数,-24+4*指数)
优于
尾数*exp2(-24+4*指数)
ldexp
就是针对这类情况而设计的,它将有效位和指数组合成浮点值(或通过指数的整数值调整现有值),它避免了
exp2
的数值问题,因为
exp2
必须处理非整数参数