一文解决前端JS小数运算精度问题

 更新时间:2024年02月21日 08:18:51   作者:Katrin  
在做项目的时候,前端需要在表格的底部做一个汇总的功能,在采用reduce对当前属性所有值汇总时,发现汇总结果存在好长的小数位,本文给大家介绍了如何解决前端JS小数运算精度问题,需要的朋友可以参考下

前言

在做项目的时候,前端需要在表格的底部做一个汇总的功能,在采用reduce对当前属性所有值汇总时,发现汇总结果存在好长的小数位,本以为后端的数据就存在精度这么小的数据,后来,检查发现后端精度只有三位小数,但前端计算结果为什么会这样呢?

JS存在精度问题

在控制台可以试一下
0.1 + 0.2 的结果是0.30000000000000004
js的运算下 0.1 + 0.2 != 0.3

由于计算机在存储和计算数字的时候,使用的是二进制形式,有些十进制数据再转换成二进制时,无法精确表示。

JS在数字运算的时候,当存在浮点数的运算时,就有可能会出现精度误差,有些小数无法用二进制精确表示。

JavaScript采用的是双精度(64位)浮点运算规则,遵循的是IEEE二进制浮点数算法标准。其中有1位用作符号位,11位为阶码,尾数有52位。有兴趣详细了解的可以查阅相关资料。

比如
十进制0.1 -> 二进制表示为0.0001 1001 1001 1001...(1100循环)
十进制0.2 -> 二进制表示为0.0011 0011 0011 0011...(0011循环)
EEE 754 标准的 64 位双精度浮点数的小数部分最多支持53位二进制位,所以两者相加之后得到二进制为:
0.1 + 0.2 = 
0.0100110011001100110011001100110011001100110011001100 
因浮点数小数位的限制而截断的二进制数字,再转换为十进制,就成了0.30000000000000004。

解决方案

思路:

  • 将小数转化成整数进行计算,规避浮点数运算问题。
  • 整数的加减乘运算结果不会出现浮点数,不会存在精度问题,但除法会出现浮点数,因此用toFixed()方法截掉无效的小数位。
  • 将string转回number输出
/** 封装一个公共方法numberCalculate() 用于浮点数运算 */
//num1 num2传入两个值 symbol +-*/符号
numberCalculate(num1: number, num2: number, symbol: string) {
    var str1 = num1.toString(), str2 = num2.toString(), result, str1Length, str2Length
    try {
        //获取小数点后的精度
        str1Length = str1.split('.')[1].length 
    } 
    catch (error) { 
        //解决整数没有小数点方法
        str1Length = 0 
    }
    try { 
        str2Length = str2.split('.')[1].length 
    } catch (error) { 
        str2Length = 0 
    }
    // 取两个数的最小精度,即小数点后数字的最大长度
    var maxLen = Math.max(str1Length, str2Length)
    // step将两个数都转化为整数至少小数点后移多少位
    var step = Math.pow(10, maxLen)

    switch (symbol) {
        case "+":
        // toFixed()根据最小精度截取运算结果
        result = ((num1 * step + num2 * step) / step).toFixed(maxLen)
        break;
        case "-":
        result = ((num1 * step - num2 * step) / step).toFixed(maxLen)
        break;
        case "*":
        result = (((num1 * step) * (num2 * step)) / step / step).toFixed(maxLen)
        break;
        case "/":
        result = ((num1 * step) / (num2 * step)).toFixed(maxLen)
        break;
        default:
        break;
    }
    // 由于toFixed方法返回结果是字符串,还需要转回number输出
    return Number(result)
}

0.1 + 0.2的计算,就可以调用numberCalculate(0.1,0.2,'+')进行计算了。

以上就是一文解决前端JS小数运算精度问题的详细内容,更多关于JS小数运算精度的资料请关注脚本之家其它相关文章!

相关文章

  • JS原型链怎么理解

    JS原型链怎么理解

    本文重点给大家介绍javascript中的原型链知识,本文介绍的非常详细,具有参考借鉴价值,感兴趣的朋友一起看下吧
    2016-06-06
  • 基于事件冒泡、事件捕获和事件委托详解

    基于事件冒泡、事件捕获和事件委托详解

    这篇文章主要介绍了事件冒泡、事件捕获和事件委托,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 解决uni-app报错Error: read EBADF at Pipe . onStreamRead...

    解决uni-app报错Error: read EBADF at Pipe . onStreamRead...

    这篇文章主要介绍了uni-app报错Error: read EBADF at Pipe . onStreamRead...解决方法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • jQuery中选择查找自定义属性具有特定值的所有元素

    jQuery中选择查找自定义属性具有特定值的所有元素

    同样在HTML5可以通过data-自定义属性名来给元素添加自定义的属性名。一旦添加完成之后。通过JS可以获取以及设置自定义属性。这篇文章主要介绍了jQuery中选择查找自定义属性具有特定值的所有元素
    2023-02-02
  • 工作中比较实用的JavaScript验证和数据处理的干货(经典)

    工作中比较实用的JavaScript验证和数据处理的干货(经典)

    工作中比较实用的JavaScript验证和数据处理知识经常会用到,下面小编通过查阅相关资料及日常记录的知识分享到脚本之家平台,供大家参考
    2016-08-08
  • javascript显式类型转换实例分析

    javascript显式类型转换实例分析

    这篇文章主要介绍了javascript显式类型转换,实例分析了javascript实现类型转换的常用技巧,非常具有实用价值,需要的朋友可以参考下
    2015-04-04
  • javascript连续赋值问题

    javascript连续赋值问题

    本文通过具体的示例来给大家详细解释了下javascript的连续赋值问题,十分的实用,有需要的小伙伴可以参考下。
    2015-07-07
  • 微信小程序之间的参数传递、获取的操作方法

    微信小程序之间的参数传递、获取的操作方法

    这篇文章主要介绍了微信小程序中如何获取和传递参数,包括获取当前页面参数、单独input文本框参数的获取、表单获取参数信息、点击表格单元格信息获取行ID以及前端页面跳转传递多个参数等,感兴趣的朋友跟随小编一起看看吧
    2025-01-01
  • java实现单链表增删改查的实例代码详解

    java实现单链表增删改查的实例代码详解

    在本篇文章里小编给大家整理了关于java实现单链表增删改查的实例内容,需要的朋友们可以参考下。
    2019-08-08
  • 分享十八个杀手级JavaScript单行代码

    分享十八个杀手级JavaScript单行代码

    这篇文章主要给大家分享了十八个杀手级JavaScript单行代码,这些单行代码可以帮助你提高工作效率并可以帮助调试代码,对大家学习或者使用JavaScript具有一定的参考学习价值,需要的朋友可以参考下
    2021-10-10

最新评论