关于f64::from_bits与std::bit_cast转换double为0.78125的原理问询
双精度浮点数位解析:为什么0x3fe9000000000000对应0.78125?
让我们一步步拆解IEEE 754双精度浮点数的位结构,就能搞懂这个转换的逻辑,同时解决你手动计算时遇到的问题。
先回顾双精度浮点数的标准布局
双精度(f64/double)是64位的,按IEEE 754标准拆成三个部分:
- 符号位(1位):最高位,0代表正数,1代表负数
- 指数位(11位):存储的是偏移后的指数,偏移量固定为
1023(也就是2^11/2 - 1) - 尾数位(52位):只存尾数的小数部分,隐含一个最高位的
1,所以实际尾数是1 + (尾数位数值 / 2^52)
最终浮点数的计算公式是:
value = (-1)^符号位 × (1 + 尾数分数) × 2^(存储指数 - 1023)
拆解目标十六进制值:0x3fe9000000000000
我们把这个64位十六进制值对应到各个字段:
- 符号位:最高位是
0(十六进制0x3的二进制是0011,最高位为0)→ 这是个正数 - 指数位:取前11位(对应十六进制的
0x3fe),转十进制是1022- 实际有效指数 = 存储指数 - 偏移量 =
1022 - 1023 = -1
- 实际有效指数 = 存储指数 - 偏移量 =
- 尾数位:剩下的52位是
0x9000000000000,转十进制是9 × 2^48- 尾数分数 = 尾数位数值 / 2^52 =
(9 × 2^48) / 2^52 = 9 / 2^4 = 9/16 = 0.5625 - 实际尾数 =
1 + 0.5625 = 1.5625
- 尾数分数 = 尾数位数值 / 2^52 =
计算最终结果
把这些值代入公式:
value = 1 × 1.5625 × 2^(-1) = 1.5625 / 2 = 0.78125
至于f64::from_bits和C++的std::bit_cast<double>,它们做的是完全一样的事情——直接把64位整数的二进制位映射到双精度浮点数的IEEE 754结构上,没有任何数值转换,所以结果自然完全一致。
解决你手动计算的疑惑
你用的公式x = (1+Mx/L)*2^(Ex-B)是正确的,但大概率是在计算Mx/L时出了错:
Mx是尾数位的存储值0x9000000000000,不是单纯的9,它等于9 << 48(也就是9乘以2的48次方)L=2^52,所以Mx/L = 9×2^48 / 2^52 = 9/16,而不是9/2^52Ex是存储的指数值1022,B=1023,所以2^(Ex-B)=2^-1=0.5
代入后就是(1 + 9/16) × 0.5 = 25/16 × 1/2 = 25/32 = 0.78125,和预期结果一致。
另外要注意,你熟悉的快速平方根倒数是针对单精度(32位)浮点数的,它用的是8位指数+23位尾数,偏移量是127,和双精度的参数完全不同,切换到双精度时一定要替换对应的偏移量和尾数位数哦。
内容的提问来源于stack exchange,提问作者Dev
相关产品推荐
相关产品推荐

