js的浮点数加法
js的浮点数加法
佣兵0926 发表于2年前
js的浮点数加法
  • 发表于 2年前
  • 阅读 1180
  • 收藏 0
  • 点赞 1
  • 评论 0

【腾讯云】如何购买服务器最划算?>>>   

摘要: js的浮点数计算有bug,不过,解决方案在网上一搜一大把,搜到的结果多是代码罗列,今天咬文嚼字一下,专门讨论js浮点数加法的计算细节

“浮点数”是计算机专有名词,它的权威解释感觉挺复杂,平时就是当做“小数”的别名,有“点”就是“浮点数”了。

1、问题

js计算0.1+0.2结果是:

2、网上找的解决方案

function accAdd(arg1,arg2){  
    var r1,r2,m;  
    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))  
    return (arg1*m+arg2*m)/m  
}

3、本人优化

上述代码,在拿try catch当if else用,用来处理参数是整数的情况,因为整数时arg2.toString().split(".")[1]的结果是undefined,undefined.length会报错,然后catch到了之后,说明是整数,然后按照整数的情况处理。

代码倒是简洁了,但try catch是用来捕获异常的,这么做是不是有点太重了?

关于,try catch参见大牛的文章http://taobaofed.org/blog/2015/10/28/try-catch-runing-problem/

所以我把try catch改成了if else,代码:

function accAdd(arg1,arg2){  
    var r1,r2,m;
    if(parseInt(arg1)==arg1){
        r1=0;
    }else{
        r1=arg1.toString().split(".")[1].length;
    }
    if(parseInt(arg2)==arg2){
        r2=0;
    }else{
    	r2=arg2.toString().split(".")[1].length
    }
    m=Math.pow(10,Math.max(r1,r2))  
    return (arg1*m+arg2*m)/m  
}


4、方法解析

上述的加法函数大体经历了以下这些步骤:

4.1、将浮点数转化成字符串,以小数点为基准,做字符串截取操作,对小数点后的字符串,做长度计算,得到小数的位数

4.2、比较等待计算的两个数的小数位数,以小数位数最多的为基准,将两个数乘以10的相同次方,变成两个整数,做整数加法,再除以前面10的相同次方,做整10除法,得到结果

4.3、结果是,两个浮点数同时乘以一个10的若干次方,又除以这个10的若干次方,结果没变,却绕过了浮点数的计算,得到了正确结果

4.4、(arg1*m+arg2*m)/m  和arg1+arg2是相等的,这其实是小学四年级乘法分配律的反向应用,

分配律说(arg1*m+arg2*m)和(arg1+arg2)*m是相等的,

所以(arg1*m+arg2*m)/m其实和(arg1+arg2)*m/m是相等的,

(arg1+arg2)*m/m就是arg1+arg2。

饶了一圈回到原点,像是什么都没做,其实绕过了浮点数计算

PS

4.4关于“乘法分配律”的说辞,也许很多人觉得废话,想当初小学学这个时就觉得这是废话,觉得肯定是那样的,怎么还有个定律啊,可这确实就是定律,此处还是定律的反向应用,提这个确实有点怀念以往的意思。想想曾经数学的一些证明题,总觉得,tmd就是这样的,还用证明吗,可是题目就是要你证明,因为这是逻辑,想想真怀念那个时光啊

共有 人打赏支持
粉丝 4
博文 56
码字总数 28941
×
佣兵0926
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: