[踩坑] 关于js四则运算时遇到的浮点数精度问题

本文探讨了JavaScript中遇到的四则运算精度丢失问题,分析了原因(有限位数、舍入误差、二进制表示和运算顺序),提供了调整运算顺序、小数转整数计算、使用Decimal.js或Big.js库以及利用Number.EPSILON比较浮点数的方法。并通过实例展示了这些解决方案。
摘要由CSDN通过智能技术生成

1.遇到的问题

        在JS计算四则运算时会遇到精度丢失的问题。

2.问题分析

        问题原因是Javascript采用了IEEE-745浮点数表示法,这种分析法不能精确的表示类似0.1这样的数字。具体原因包括以下几点:

  1. 有限的位数:计算机内部用有限的位数来表示浮点数,例如JavaScript中的64位双精度浮点数,无法精确表示所有的十进制小数。

  2. 舍入误差:在进行浮点数运算时,由于舍入误差的累积,可能会导致最终结果与预期结果略有不同。

  3. 二进制表示问题:有些十进制小数无法准确表示为有限位的二进制小数,例如1/3在十进制下是无限循环小数0.3333...,在二进制下也无法精确表示。

  4. 运算顺序:浮点数运算的顺序可能会影响最终结果的精度,特别是涉及到大量浮点数运算时。

3.解决方案

   (1).对于我遇到的这种情况,可以通过调整运算顺序,将.toFixed操作放在最后执行

   (2).对于其他情况,可以将小数转换为整数进行计算,然后再将结果转换回小数。具体步骤如下:

        2.1将小数转换为整数:将小数乘以一个足够大的倍数,使小数部分变为整数。例如,如果要处理两位小数,可以将小数乘以100。

        2.2进行整数计算:对得到的整数进行需要的计算,可以使用整数运算来确保精度。

        2.3将结果转换回小数:最后,将整数结果除以之前乘的倍数,将其转换回原始的小数形式。 

// 将小数转换为整数进行计算
let decimal = 3.14159;
let multiplier = 100; // 乘以100,处理两位小数

let integer = Math.round(decimal * multiplier); // 将小数转换为整数
console.log("转换为整数后的结果:", integer);

// 进行整数计算
let resultInteger = integer * 2; // 乘以2,示例整数计算
console.log("整数计算后的结果:", resultInteger);

// 将结果转换回小数
let resultDecimal = resultInteger / multiplier; // 将整数结果转换回小数
console.log("转换回小数后的结果:", resultDecimal);

(3).使用专门的库,如Decimal.js或Big.js,提供了更精确的数学运算功能,可以避免浮点数精度问题。

(4).可以使用js机器精度来进行比较,判断两个浮点数的差值是否在一个很小的范围内。ES6 开始,该值定义在 Number.EPSILON 中,

function areEqual(num1, num2) {
    return Math.abs(num1 - num2) < Number.EPSILON;
}

let a = 0.1 + 0.2;
let b = 0.3;

if (areEqual(a, b)) {
    console.log("a 和 b 相等");
} else {
    console.log("a 和 b 不相等");
}

4.更多浮点数精度相关参考推荐

阮一峰的网络日志-浮点数的二进制表示

知乎-浮点数的前世今生

  • 23
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值