JS的浮点型乘除法无法精确计算问题处理

JS的精确计算问题是一些做金融或一些需要计算功能的一个痛点,例如:

// 加法
0.1 + 0.2 = 0.30000000000000004
0.1 + 0.7 = 0.7999999999999999
0.2 + 0.4 = 0.6000000000000001
 
// 减法
0.3 - 0.2 = 0.09999999999999998
1.5 - 1.2 = 0.30000000000000004
 
// 乘法
0.8 * 3 = 2.4000000000000004
19.9 * 100 = 1989.9999999999998
 
// 除法
0.3 / 0.1 = 2.9999999999999996
0.69 / 10 = 0.06899999999999999
 
// 比较
0.1 + 0.2 === 0.3 // false
(0.3 - 0.2) === (0.2 - 0.1) // false

常见的解决方式使用math.js,如果在vue或react项目中(下方以vue为例)会用对应的mathjs。

官网: http://mathjs.org/
cdn地址:https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.0.0/math.js

JS中的应用示例:

<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.0.0/math.js"></script>
<script type="text/javascript">
function fn_click(p){
  var a , b;
  a=0.7;
  b=0.1;
  if(p==1){
    alert(a+b);
  }else if(p==2){
    alert(eval("a+b"));
  }else if(p==3){
    math.config({
      number: 'BigNumber'
    });
    var result = math.parser().eval(a + "+" + b)
    alert(result);
  }
}
</script>
</head>
<body>
  <input type="button" value="0.7+0.1" onclick="fn_click(1);" />
  <input type="button" value="eval(0.7+0.1)" onclick="fn_click(2);" />
  <input type="button" value="mathjs(0.7+0.1)" onclick="fn_click(3);" />
</body>
</html>

在Vue中的应用示例:
在这里插入图片描述
在这里插入图片描述

但是,这样用mathjs对于比较大数字就会有不少的问题,下边我们用原生js的方式封装一个解决这样问题的方法
乘法
const NumberMul = function(arg1, arg2) {
    var m = 0;
    var s1 = arg1.toString();
    var s2 = arg2.toString();
    try {
        m += s1.split(".")[1].length;
    } catch (e) {}
    try {
        m += s2.split(".")[1].length;
    } catch (e) {}
 
    return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
}
加法
const NumberAdd = function(arg1, arg2) {
    var r1, r2, m, n;
    try {
        r1 = arg1.toString().split(".")[1].length
    } catch (e) {
        r1 = 0
    }
    try {
        r2 = arg2.toString().split(".")[1].length
    } catch (e) { 
        r2 = 0 
    } 
    m = Math.pow(10, Math.max(r1, r2))
    n = (r1 >= r2) ? r1 : r2;
    return ((arg1 * m + arg2 * m) / m).toFixed(n);
}
减法
const NumberSub = function(arg1, arg2) {
    var re1, re2, m, n;
    try {
        re1 = arg1.toString().split(".")[1].length;
    } catch (e) {
    re1 = 0;
    }
    try {
        re2 = arg2.toString().split(".")[1].length;
    } catch (e) {
        re2 = 0;
    }
    m = Math.pow(10, Math.max(re1, re2)); 
    n = (re1 >= re2) ? re1 : re2;
    return ((arg1 * m - arg2 * m) / m).toFixed(n);
}
除法
// 除数,被除数, 保留的小数点后的位数
const NumberDiv = function (arg1,arg2,digit){
    var t1=0,t2=0,r1,r2;
    try{t1=arg1.toString().split(".")[1].length}catch(e){}
    try{t2=arg2.toString().split(".")[1].length}catch(e){}
    r1=Number(arg1.toString().replace(".",""))
    r2=Number(arg2.toString().replace(".",""))
    //获取小数点后的计算值
   var result= ((r1/r2)*Math.pow(10,t2-t1)).toString()
    var result2=result.split(".")[1];
    result2=result2.substring(0,digit>result2.length?result2.length:digit);
 
    return Number(result.split(".")[0]+"."+result2);
}

注意:被除数arg2 不能为0,这里就不做判断了,使用的小伙伴注意了

使用方式(以乘法方式为例)
console.log(NumberMul(0.0058,100))
如果在vue中使用的话,也可以将方法放入全局,也可以页面中单个应用
例如(以全局方式为例)
Vue.prototype.NumberMul = function(arg1, arg2) {
    var m = 0;
    var s1 = arg1.toString();
    var s2 = arg2.toString();
    try {
        m += s1.split(".")[1].length;
    } catch (e) {}
    try {
        m += s2.split(".")[1].length;
    } catch (e) {}
 
    return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
}

如果本文对你有很大用处请你点个赞吧!

本文参考:https://www.cnblogs.com/bushui/p/12150947.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值