JavaScript 小数精度问题

JavaScript 小数精度问题

在 JavaScript 中,你可能遇到这样的现象:

js 复制代码
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(2.3 * 10); // 23
console.log(2.3 * 100); // 229.99999999999997
console.log(2.3 * 10 === 23); // true
console.log(2.3 * 100 === 230); // false

1. 浮点数的本质

JavaScript 的数字都是 64 位 IEEE 754 双精度浮点数。

  • 64 位组成:
arduino 复制代码
1 bit   | 符号位
11 bits | 指数
52 bits | 尾数 / 小数部分
  • 二进制无法精确表示部分十进制小数:
ini 复制代码
十进制 0.1 = 二进制 0.0001100110011001100...(无限循环)

所以 2.3 只是一个近似值:

复制代码
2.3 ≈ 2.29999999999999982236431605997495353221893310546875

2. 案例:2.3 _ 10 vs 2.3 _ 100

2.3 * 10

lua 复制代码
2.3 ≈ 2.2999999999999998
* 10
22.999999999999996  <-- 舍入成二进制 23

二进制示意:

makefile 复制代码
真实值: 22.999999999999996
存储值: 23
显示值: 23
比较: 2.3*10 === 23  → true

2.3 * 100

lua 复制代码
2.3 ≈ 2.2999999999999998
* 100
229.99999999999997  <-- 无法舍入成二进制 230

二进制示意:

makefile 复制代码
真实值: 229.99999999999997
存储值: 229.99999999999997
显示值: 229.99999999999997
比较: 2.3*100 === 230 → false

3. 打印规则

  • JS 打印数字时选择 最短且能还原原数值的十进制表示。

  • 能显示整数就显示整数,不能就显示近似小数。

    22.999999999999996 → 23
    229.99999999999997 → 229.99999999999997

查看真实存储值:

scss 复制代码
console.log((2.3 * 10).toPrecision(17));  // "23"
console.log((2.3 * 100).toPrecision(17)); // "229.99999999999997"

4. 浮点数误差可视化

复制代码
2.3 的近似值:   2.2999999999999998
乘 10 → 23 (可舍入)
乘 100 → 229.99999999999997 (无法舍入)

5. 解决方法

5.1 四舍五入

javascript 复制代码
Math.round(2.3 * 100); // 230

5.2 保留小数

scss 复制代码
(0.1 + 0.2).toFixed(2); // "0.30"

5.3 使用整数运算

ini 复制代码
let price = 230;  // 2.3元 -> 230分
let total = price * 10;
console.log(total / 100); // 23

5.4 使用大数库

javascript 复制代码
import { Decimal } from "decimal.js";
let x = new Decimal(2.3).times(100);
console.log(x.toString()); // "230"

6. 总结

  • JS 数字是采用 64 位 IEEE 754 双精度浮点数存储,小数可能无法精确表示,这其实并不是 js 的问题,而是双精度浮点数机制的问题,同样 java 也会存在小数精度丢失的问题。
  • 打印整数或小数由 最短表示法规则 决定。
  • 严格相等比较(===)取决于浮点数的 二进制存储。
  • 2.3*10 === 23 是因为误差正好舍入,2.3*100 !== 230 是误差无法舍入。
  • 遇到小数运算、金额计算时,最好用 四舍五入、整数运算或大数库。

查看真实存储值:

scss 复制代码
console.log((2.3*100).toPrecision(17)); // 229.99999999999997
相关推荐
believed_breadfruit2 分钟前
我开源了一个HTML 分页导出工具,解决了复杂页面的内容截断、跨页错乱和长文档白屏问题
前端·javascript·github
福狼7 分钟前
从“网墙”到柔性曲面:一次 WebGPU 波浪的逆向分析与重建
前端·逆向
宝哥聊编程15 分钟前
主流 Agent 平台对比:Coze、Dify、飞书、扣子、OpenClaw 落地实操手册
前端·人工智能·飞书
时间的情敌37 分钟前
Vue3 + Cesium 实战:本地上传 GLB 模型、模型上叠加 GLB、点击控制透明度
前端·vue.js·cesium
拖孩41 分钟前
流量主门槛从 500 降到 100,我的小程序上线 18 小时够到了线
前端·后端·微信小程序
深蓝AI1 小时前
编码 Agent 的界面味靠提示词压不住:Impeccable 用无模型规则拦同一套模板
前端·程序员
CCIE-Yasuo1 小时前
网络安全-Javascript基础
javascript·安全·web安全
January12072 小时前
【AI方法笔记】2026-11-02:模型流式吐 JSON 时,前端会遇到四种崩法
前端·人工智能·笔记·json
asdzx672 小时前
C# 操作 PDF 元数据:从属性写入到字段提取的完整流程
前端·pdf·c#
幻境如梦丶皆为虚2 小时前
从零写一个 DSH 插件:在左侧菜单栏加一个「测试」
开发语言·javascript·ecmascript