double 是计算机编程语言里最常用的双精度浮点数类型,核心作用就是存储带小数的数值,相比单精度 float 它拥有更高的精度和更大的数值范围,绝大多数编程语言默认的小数类型就是 double,日常写代码做计算科学运算金融计算绘图计算的时候都会优先选用它,之所以应用这么广泛,是因为它遵循 IEEE754 双精度标准,占用固定 8 个字节也就是 64 位存储空间,这 64 位被划分成符号位指数位尾位三个部分,符号位决定数字正负,指数位负责管理数值的大小量级,尾位用来保存有效数字,这套设计让它既能表示非常大或者非常小的数字,又能保留更多有效位数,不过它本质是二进制近似存储,这也是后面很多精度丢失问题的根本来源,很多新手刚接触 double 的时候会误以为它可以精确保存所有十进制小数,实际在运算的时候很容易出现 0.1 加 0.2 不等于 0.3 这类经典现象,理解它的存储原理之后,再掌握声明赋值运算比较以及精度处理的完整步骤,就能避开大部分使用坑点,在项目里稳定使用 double 完成数值计算任务。
一 double 核心基础属性
double 全称 double precision floating point,也就是双精度浮点数,主流编程语言 C C++ Java C JavaScript 等都内置支持这个类型,它固定占用 8 字节内存,一共 64 比特,按照 IEEE754 标准拆分结构如下表格
| 组成部分 | 占用比特位 | 功能说明 |
|---|---|---|
| 符号位 | 1 位 | 0 代表正数,1 代表负数 |
| 指数位 | 11 位 | 偏移指数,支持很大的正负量级 |
| 尾数位 | 52 位 | 保存有效数字,决定有效精度 |
有效十进制精度大约是 15 到 17 位有效数字,数值范围大概是正负 1.7E308,这个范围远大于 float 的正负 3.4E38,float 只有 4 字节,有效精度大约 6 到 7 位,所以只要计算对精度有要求,就不要用 float,直接选用 double。
二 double 基础使用步骤
第一步 变量声明,不同语言写法略有区别,C 和 C++ 写法是 double 变量名,Java 写法同样是 double 变量名,声明之后就可以给变量赋值,可以直接写整数也可以写小数。
第二步 赋值与基础运算,支持加减乘除取余幂运算等常规数学运算,运算过程里面整数会自动隐式转换成 double 类型参与计算。
第三步 数值比较,这里是重点,不能直接用等号判断两个 double 是否相等,因为二进制近似存储带来微小误差,推荐做法是设置一个极小容差,判断两个数值差值绝对值小于容差就认为相等。
第四步 精度处理,当业务要求精确十进制计算,比如金额计算,就不能单纯依赖 double,需要结合四舍五入或者改用专门高精度类型,避免累计误差。
三 double 常见问题原理
最典型就是十进制小数无法精准转成二进制,像 0.1 这个十进制小数,转换成二进制是无限循环小数,double 只能截断保存近似值,多次累加之后误差会放大,最终输出结果和肉眼预期不一样。另外还有特殊值,double 可以保存无穷大 Infinity,非数字 NaN,运算除以 0 的时候就会生成这类特殊值,后续继续运算会污染整个计算链路。
四 double 和 float 对比
| 对比项 | double | float |
|---|---|---|
| 内存占用 | 8 字节 | 4 字节 |
| 有效十进制位数 | 15 到 17 位 | 6 到 7 位 |
| 数值上限 | 约 1.7E308 | 约 3.4E38 |
| 适用场景 | 科学计算 金融计算 高精度运算 | 图形渲染 内存敏感场景 |
五 double 使用最佳实践
第一 不要直接用 == 比较 double,统一使用容差比较方案。
第二 金融货币业务优先评估是否需要高精度十进制类型,不要默认 double。
第三 长时间迭代累加运算,定期检查误差累积情况。
第四 输出 double 数值的时候按需格式化,避免输出超长无意义尾数。
【常见问题】
问题 1 double 为什么会出现精度丢失
回答 1 double 是 IEEE754 二进制浮点数,很多十进制小数没办法转换成有限二进制,double 只能保存近似值,多次运算之后误差累积,所以 double 会出现精度丢失,对精度敏感业务要额外做舍入处理。
问题 2 double 能不能直接用来做金额计算
回答 2 double 不推荐直接做金额计算,因为 double 本身存在近似存储特性,累加之后容易出现分位误差,如果必须使用 double,需要在每一步运算后做定点舍入,更稳妥方案是更换高精度十进制类型。
问题 3 double 和 float 该怎么选择
回答 3 如果对有效数字要求高,数值跨度大,优先选择 double,如果项目对内存占用非常敏感,精度要求低,比如三维图形顶点数据,可以选择 float,绝大多数业务默认首选 double。
问题 4 double 里面的 NaN 是什么含义
回答 4 NaN 是 Not a Number,代表非数字,属于 double 类型特殊值,一般是非法数学运算产生,比如负数开平方,NaN 参与任何运算结果依旧是 NaN,代码里要提前判断拦截。
【免责申明】
本文内容基于通用编程语言 IEEE754 标准相关知识进行讲解,不同编程语言编译器运行环境存在细微差异,实际项目开发请结合官方文档验证,本文仅作技术学习参考,不构成任何开发方案保证,因直接照搬代码产生的业务损失,由使用者自行承担。

