“浮点数”是计算机专有名词,它的权威解释感觉挺复杂,平时就是当做“小数”的别名,有“点”就是“浮点数”了。
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就是这样的,还用证明吗,可是题目就是要你证明,因为这是逻辑,想想真怀念那个时光啊