问题描述
试图弄清楚它是如何工作的,但我无法围绕我所代表的东西。 我了解我们分配了 unsigned long long ,因为它包含与 float 相同的位数。但是 i 到底代表什么?
我最好的解释是,我们试图将双精度数转换为无符号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 << " ";
}
}
解决方法
在大多数(但不是全部)平台上,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,subnormals,signed zeros),但这是基本思想。如果您需要更深入的参考,那么最好的书是Michael L. Overton,"Numerical Computing with IEEE Floating Point Arithmetic"。
请注意,取消引用*(unsigned long long int *)&d
是未定义的行为,正如其他人所评论的那样。如果您确实希望将double的位转换为64位int,则安全的方法是通过memcpy:
uint64_t bits;
std::memcpy(&bits,&d,sizeof(d));