IBM Single Precision Floating Point data conversion to intended value

血红的双手。 提交于 2019-12-17 13:40:33

问题


I need to read values from a binary file, the data format is IBM single Precision Floating Point (4-byte Hexadecimal Exponent Data) and use the value as a decimal number. I have C++ code that reads from the file and takes out each byte and stores it like so

 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]);
            }
        }

This prints out the hexadecimal values of each byte.

this picture specifies IBM single precision floating point IBM single precision floating point I do not understand what a 24-bit positive binary fraction is. I do know how to convert between hex<->dec<->binary so my basic understanding would be to take all the q's and treat them as one very long binary segment that would use Q24(2)^(23) as the largest value while adding all the preceding values together, and then just times the number by 10^-24 . But my intuition tells me this is wrong. Clarification on what a radix point or MSB is would be helpful.


回答1:


The format is actually quite simple, and not particularly different than IEEE 754 binary32 format (it's actually simpler, not supporting any of the "magic" NaN/Inf values, and having no subnormal numbers, because the mantissa here has an implicit 0 on the left instead of an implicit 1).

As Wikipedia puts it,

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

If we imagine that the bytes you read are in a uint8_t b[4], then the resulting value should be something like:

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.;

Notice that here I calculated the result in a double, as the range of a IEEE 754 float is not enough to represent the same-sized IBM single precision value (also the opposite holds). Also, keep in mind that, due to endian issues, you may have to revert the indexes in my code above.


Edit: @Eric Postpischil correctly points out that, if you have C99 or POSIX 2001 available, instead of mantissa * exp2(-24 + 4*exponent) you should use ldexp(mantissa, -24 + 4*exponent), which should be more precise (and possibly faster) across implementations.



来源:https://stackoverflow.com/questions/45227913/ibm-single-precision-floating-point-data-conversion-to-intended-value

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!