【问题标题】:How to convert float to IEEE754 Double Precision format by using union and struc in C?如何在 C 中使用 union 和 struc 将浮点数转换为 IEEE754 双精度格式?
【发布时间】:2013-05-24 08:52:40
【问题描述】:

我写了这个程序:

#include <stdio.h>
#include <stdint.h>
/*
 * See also : http://class.ece.iastate.edu/arun/CprE281_F05/ieee754/ie5.html
 */

union FloatingPointSinglePrecisionIEEE754 {
    struct {
        unsigned int mantissa : 23;
        unsigned int exponent : 8;
        unsigned int sign : 1;
    } raw;
    float f;
} fnumber;

union FloatingPointDoublePrecisionIEEE754 {
    struct {
        uint64_t mantissa : 52;
        unsigned int exponent : 11;
        unsigned int sign : 1;
    } raw;
    double d;
} dnumber;



int main() {

    printf("sign\texponent\tmantissa\n");

    fnumber.f = -6.8;
    printf("%x\t%x\t\t%x\n",
            fnumber.raw.sign,
            fnumber.raw.exponent,
            fnumber.raw.mantissa); 


    dnumber.d = -6.8;
    printf("%x\t%x\t\t%x\n",
            dnumber.raw.sign,
            dnumber.raw.exponent,
            dnumber.raw.mantissa); 


return 0;
}

对于单精度,我得到了真正的输出,但对于双精度,程序失败了。任何人都可以帮助我如何编写双精度转换器?

【问题讨论】:

  • “程序失败”是什么意思?它会产生什么结果?
  • 这个程序产生浮点的符号、指数和尾数部分
  • 我的问题是“它在什么意义上失败了?”它会崩溃吗?还是会产生意想不到的输出?还是不编译?
  • 对于浮点数,输出为真。 (参见 class.ece.iastate.edu/arun/CprE281_F05/ieee754/ie5.html )但对于双数,输出不正确。我好糊涂!!!
  • 程序已编译,但第二个输出不正确。

标签: c floating-point printf ieee-754 bit-fields


【解决方案1】:

下面的程序似乎对我有用。我明白了:

sign    exponent    mantissa
1   81      59999a
1   401     b333333333333

我所做的两个更改是在printf() 中使用正确的C99 格式PRIx64(有关这些格式的信息,请参阅this wikipedia page)以及在union FloatingPointDoublePrecisionIEEE754 中的结构中的位字段使用相同的基本类型.众所周知,位域的指定不足,但使用不同的基本类型可能会导致编译器开始一个新单词,而不是您想要的。

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
/*
 * See also : http://class.ece.iastate.edu/arun/CprE281_F05/ieee754/ie5.html
 */

union FloatingPointSinglePrecisionIEEE754 {
    struct {
        unsigned int mantissa : 23;
        unsigned int exponent : 8;
        unsigned int sign : 1;
    } raw;
    float f;
} fnumber;

union FloatingPointDoublePrecisionIEEE754 {
    struct {
        uint64_t mantissa : 52;
        uint64_t exponent : 11;
        uint64_t sign : 1;
    } raw;
    double d;
} dnumber;



int main() {

    printf("sign\texponent\tmantissa\n");

    fnumber.f = -6.8;
    printf("%x\t%x\t\t%x\n",
            fnumber.raw.sign,
            fnumber.raw.exponent,
            fnumber.raw.mantissa); 


    dnumber.d = -6.8;
    printf("%x\t%x\t\t%" PRIx64 "\n",
            dnumber.raw.sign,
            dnumber.raw.exponent,
       (uint64_t)dnumber.raw.mantissa); 


return 0;
}

【讨论】:

    【解决方案2】:

    可能是您的printf 失败,因为您尝试使用简单的%x 格式化程序输出64 位无符号整数。将 %xl 用于“长”无符号整数:

    dnumber.d = -6.8;
    printf("%x\t%x\t\t%xl\n",  // note the %xl format specifier for the mantissa
            dnumber.raw.sign,
            dnumber.raw.exponent,
            dnumber.raw.mantissa); 
    

    见printf reference

    【讨论】:

    • 我没有测试过,没有。试试%ul?但这不会给你十六进制 - 只是一个普通的 unsigned int_64
    • 您的意思分别是%lx 和%lu。 %xl 只是 %x 后跟文本 "l"。
    【解决方案3】:

    python代码简单如下:

    def hb(a):
        ab = bin(int(a[:3],16))[2:]
        if len(ab)==12:
            sgn=1
            ex=int(ab[1:], 2)-1023
        else:
            sgn=0
            ex=int(ab, 2)-1023
        return(((-1)**sgn)*(1.0 + ((int(a[3:],16))/(2.0**52)))*(2**ex))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-12
      • 1970-01-01
      • 1970-01-01
      • 2012-02-28
      • 1970-01-01
      相关资源
      最近更新 更多