JS浮点数精度问题

[复制链接]
发表于 2025-7-8 19:32:57 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
在JavaScript开发中,浮点数精度问题是一个常见的陷阱。本文将深入探究JavaScript中浮点数精度问题的原因、影响以及解决方案。
一、浮点数精度常见问题

(一)加法运算
  1. console.log(0.1 + 0.2); // 0.30000000000000004
  2. console.log(0.7 + 0.1); // 0.7999999999999999
  3. console.log(0.2 + 0.4); // 0.6000000000000001
  4. console.log(2.22 + 0.1); // 2.3200000000000003
复制代码
(二)减法运算
  1. console.log(1.5 - 1.2); // 0.30000000000000004
  2. console.log(0.3 - 0.2); // 0.09999999999999998
复制代码
(三)乘法运算
  1. console.log(19.9 * 100); // 1989.9999999999998
  2. console.log(19.9 * 10 * 10); // 1990
  3. console.log(9.7 * 100); // 969.9999999999999
  4. console.log(39.7 * 100); // 3970.0000000000005
复制代码
(四)除法运算
  1. console.log(0.3 / 0.1); // 2.9999999999999996
  2. console.log(0.69 / 10); // 0.06899999999999999
复制代码
(五)四舍五入保留小数位数
  1. console.log((1.335).toFixed(2)); // 1.33
复制代码
二、为什么会有这样的问题

(一)浮点数的存储方式

在JavaScript中,全部数字都以64位浮点数形式存储,即使整数也是如此。这种存储方式基于IEEE 754标准,此中64位的分别如下:

  • 符号位(1位):表现正负数,0表现正数,1表现负数。
  • 指数位(11位):表现次方数。
  • 尾数位(52位):存储小数部分,超出部分自动进一舍零。
(二)二进制表现的范围性

浮点数在盘算机中以二进制形式存储,但某些十进制小数无法准确表现为二进制小数。例如,0.1和0.2在二进制中是无限循环小数,因此在存储时会被截断,导致精度丢失。
(三)JavaScript的Number范例

JavaScript中的Number范例同一按浮点数处理惩罚,整数也是按最大54位来盘算的。因此,当数值高出安全范围(Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER)时,就会出现精度问题。
三、解决方案

(一)使用第三方库

为了准确处理惩罚浮点数运算,可以使用一些成熟的第三方库,如Math.js、decimal.js和big.js。
Math.js

Math.js是一个功能强大的数学库,支持多种数据范例和操作。
  1. const math = require('mathjs');
  2. console.log(math.add(0.1, 0.2)); // 0.3
复制代码
decimal.js

decimal.js提供任意精度的十进制数值运算。
  1. const Decimal = require('decimal.js');
  2. console.log(new Decimal(0.1).plus(0.2).toNumber()); // 0.3
复制代码
big.js

big.js专注于大数运算,支持高精度的浮点数运算。
  1. const Big = require('big.js');
  2. console.log(new Big(0.1).plus(0.2).toString()); // "0.3"
复制代码
(二)自定义函数

如果不想引入第三方库,可以编写自定义函数来处理惩罚浮点数运算。以下是一个简单的加法函数示例:
  1. function add(a, b) {
  2.     const factor = 10 ** 10;
  3.     return (Math.round(a * factor) + Math.round(b * factor)) / factor;
  4. }
  5. console.log(add(0.1, 0.2)); // 0.3
复制代码
(三)避免浮点数运算

在某些情况下,可以避免直接使用浮点数运算。例如,处理惩罚货币时,可以将金额转换为整数(如分)进行盘算,最后再转换回浮点数。
  1. function addCents(a, b) {
  2.     return (Math.round(a * 100) + Math.round(b * 100)) / 100;
  3. }
  4. console.log(addCents(0.1, 0.2)); // 0.3
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表