博主的另一篇文章讲解浮点数的相关知识:

https://blog.csdn.net/ouyangxiaozi/article/details/161105232?sharetype=blogdetail&sharerId=161105232&sharerefer=PC&sharesource=ouyangxiaozi&spm=1011.2480.3001.8118

本文再讲解浮点数再计算机中存储的详细过程,比如double类型的9.721的整个转换和存储过程。

先按主流平台讲:在绝大多数 PC 和服务器上,C++ 里的 double 使用 IEEE 754 双精度格式,也就是 binary64。9.721 字面量,默认就是 double,编译器会把它转换成“最接近 9.721 的那个 binary64 值”。

1. double 的 64 位结构

double 一共 64 位,分成 3 段:

  1. 1 位符号位 sign
  2. 11 位指数位 exponent
  3. 52 位尾数字段 fraction

正规数的值按这个公式解释:

这里的 1023 是指数偏移量。


2. 9.721 先变成二进制是什么样

十进制整数部分很简单:

910=10012910​=10012​

小数部分 0.721 要靠“乘 2 取整”反复展开,它不是一个有限二进制小数,所以会变成无限展开。

前几步例如:

  1. 0.721 × 2 = 1.442,取 1
  2. 0.442 × 2 = 0.884,取 0
  3. 0.884 × 2 = 1.768,取 1
  4. 0.768 × 2 = 1.536,取 1
  5. 0.536 × 2 = 1.072,取 1

所以它的二进制大致是:

因为是无限展开,double 不可能把它完整存下,只能截断并舍入到 52 位尾数。


3. 规格化

9.721 落在区间 [8,16)[8,16),所以规格化后指数是 3

这就是写进 double 前的“规格化形式”。


4. 三段字段分别是什么

对 9.721 这个 double,三段内容是:

  1. 符号位
    0
    因为它是正数。

  2. 指数位
    真实指数是 3,存储时要加偏移量 1023

                3+1023=1026

1026 的二进制是:

                

  1. 尾数字段
    去掉规格化里隐含的前导 1 后,存这 52 位:

                0011011100010010011011101001011110001101010011111110

所以完整位模式就是:

0 | 10000000010 | 0011011100010010011011101001011110001101010011111110


5. 最终 64 位十六进制表示

把上面的 64 位合起来,得到:40237126E978D4FE

也就是:0x40237126E978D4FE

这是最常见、最方便看的表示法。

如果你的机器是常见的 x86/x64 小端序,那么内存里按地址从低到高看到的 8 个字节通常是:

FE D4 78 E9 26 71 23 40

注意:

  1. IEEE 754 规定的是位意义
  2. 小端/大端影响的是字节在内存里的摆放顺序

6. 它实际存的值并不等于数学上的 9.721

真正被存进去的精确值是:

它对应的十进制是:

9.721000000000000085265128291212022304534912109375

所以它比真正的 9.721 稍微大一点,误差大约是:

这就是为什么浮点数经常会出现“看起来一样,底层并不完全相等”的现象。


7. 你可以自己验证

下面这段代码可以把 9.721 的位模式打印出来:

#include <cstdint>
#include <cstring>
#include <iomanip>
#include <iostream>

int main() {
    double x = 9.721;
    std::uint64_t bits = 0;
    std::memcpy(&bits, &x, sizeof(x));

    std::cout << "hex bits = 0x"
              << std::hex << std::uppercase << bits << '\n';

    std::cout << std::dec << std::setprecision(30)
              << "stored value = " << x << '\n';
}

在主流 IEEE 754 平台上,通常会看到接近这样的输出:

hex bits = 0x40237126E978D4FE
stored value = 9.72100000000000008526512829121

一句话总结

double 9.721 在计算机里不是直接存“9.721 这几个十进制字符”,而是先转成二进制科学计数法,再按 IEEE 754 的 符号位 + 指数位 + 尾数位 存成 64 位。对这个数来说,最终常见的 binary64 编码是:

0x40237126E978D4FE

而它真正存储的十进制值其实是:

9.721000000000000085265128291212...

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐