【问题标题】:To convert a float / double to its IEEE754 representation in C++在 C++ 中将 float / double 转换为其 IEEE754 表示
【发布时间】:2021-01-14 16:03:33
【问题描述】:

试图弄清楚这是如何工作的,但我无法理解我所代表的内容。 我知道我们分配了一个 unsigned long long,因为它包含的位数与 float 相同。但是 i 究竟代表什么?

我最好的解释是我们试图将 double 数转换为 unsigned long long int,因为它们具有相同的位数。看来最好的方法是取消引用我们设置的指针?

任何帮助将不胜感激!

void printDouble(double d) {

unsigned long long int i = *(unsigned long long int *)&d;

for (int j = 63; j >= 0; j--) {
    std::cout << ((i >> j) & 1);

    if (j == 63) std::cout << " ";
    else if (j == 52) std::cout << " ";
}

}

【问题讨论】:

  • 这是类型双关语,它是未定义的行为,就像它在这里完成的方式一样。
  • 它的工作原理是违反 严格的别名规则,但暂时搁置一下。您循环了 64 次(i 中的每个位一个),然后右移 j 位并与 1 进行 AND 以隔离感兴趣的位并输出它。您检查 j63 还是 52 并在符号位和偏置指数之间输出一个空格,然后在偏置指数和尾数之间再次输出。
  • 代码是 UB,如前所述。它也可以作为unsigned long long int &amp;i = (unsigned long long int &amp;)d; 工作(同样是UB,但没有额外的副本并且可能更易于阅读)。
  • float 是单精度类型,使用 32 位。 double 是使用 64 位的双精度类型。 long long 保证至少为 64 位。

标签: c++ ieee-754


【解决方案1】:

在大多数(但不是全部)平台上,floatdouble 使用 IEEE 754 表示来近似实数值。有关位的含义,请参见例如https://en.wikipedia.org/wiki/IEEE_754。简而言之,在 IEEE-754 64 位双精度中,有一个符号位、一个 11 位指数和一个 52 位有效数(也称为尾数),以如下形式表示实数

sign ⋅ 2^(exponent − 1023) ⋅ (1.0 + significand / 2^52)

除此之外还有一些特殊情况(无穷大、NaNsubnormalssigned zeros),但这是基本思想。如果您正在寻找更深入的参考资料,一本很棒的书是Michael L. Overton, "Numerical Computing with IEEE Floating Point Arithmetic"

请注意,取消引用 *(unsigned long long int *)&amp;d 是未定义的行为,正如其他人所评论的那样。如果您真的想将 double 的位转换为 64 位 int,那么一种安全的方法是通过 memcpy:

uint64_t bits;
std::memcpy(&bits, &d, sizeof(d));

【讨论】:

    猜你喜欢
    • 2018-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多