我需要读取二进制文件中的值,数据格式是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]);
}
}
这将打印出每个字节的十六进制值.
此图片指定IBM单精度浮点
IBM single precision floating point
我不明白24位正二进制分数是什么.我知道如何在十六进制< - > dec< - >二进制之间进行转换,所以我的基本理解是将所有的q作为一个非常长的二进制段,它将使用Q24(2)^(23)作为将所有前面的值加在一起时的最大值,然后将数字乘以10 ^ -24.但我的直觉告诉我这是错的.我也不知道基数点或MSB是什么.
关于如何使用这些数据的任何想法?我的目标是使用每个值作为新点绘制线条.
我知道这不是很简短,但这不是一个简短的问题不能简洁的话题.
解决方法:
格式实际上非常简单,并没有特别不同于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单精度值(也相反).另外,请记住,由于endian问题,您可能必须在上面的代码中还原索引.
编辑:@Eric Postpischil正确地指出,如果你有C99或POSIX 2001可用,而不是尾数* exp2(-24 4 *指数)你应该使用ldexp(尾数,-24 4 *指数),这应该更精确(并且可能更快)跨实现.
标签:c,byte,bits 来源: https://codeday.me/bug/20190926/1819699.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。