将 float/double 转换为其 IEEE754 表示形式

问题描述 投票:0回答:2

我知道我们分配一个

unsigned long long
是因为它包含与
float
相同的位数。但
i
到底代表什么?

我最好的解释是,我们试图将双精度数转换为

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 << " ";
    }
}
c++ ieee-754
2个回答
7
投票

在大多数(但不是全部)平台上,

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

sign ⋅ 2^(exponent − 1023) ⋅ (1.0 + significand / 2^52)
除此之外还有一些特殊情况(无穷大、

NaN次正规数有符号零),但这就是基本思想。如果您正在寻找更深入的参考资料,一本很棒的书是 Michael L. Overton,“Numerical Computation with IEEE Floating Point Arithmetic”

请注意,取消引用

*(unsigned long long int *)&d

 是未定义的行为,正如其他人评论的那样。如果您确实想将 double 的位转换为 64 位 int,一种安全的方法是通过 memcpy:

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

1
投票
自 C++20 起

std::bit_cast 可以使用:

std::uint64_t bits = std::bit_cast<std::uint64_t>(d);
    
© www.soinside.com 2019 - 2024. All rights reserved.