关键字‘浮点数’的相关文章

js浮点数运算的bug

老实说在今天之前,我对javascript的浮点数运算毫无认识,觉得应该和实际运算中一样,然而,有些事情往往会出人意料。

先看一组数据:
0.1 + 0.11 = 0.21000000000000002
0.2 * 3 = 0.6000000000000001
0.7 / 10 = 0.06999999999999999

你相信吗?如果不信,那么立即打开firefox浏览器测试吧。有一点可以确信,你看到测试结果的表情,一定先是惊讶,后来是迷惑。

这里有几个demo,再来看看出现浮点数运算bug的概率,猛击之:加法乘法除法

对于这样的结果,我不知道是怎么产生的,但是既然是bug,就一定是可以hack的,思路很简单,先把所有的运算数转成int型(表达不准确,javascript的没有int、float之分),计算出两个运算数的小数点后的位数,再进行适当的运算,就可以得到原始的我们期望看到的结果了。代码如下:

加法运算:

  1. function add(num1,num2){
  2.         var reg = /\./i;
  3.     if(!reg.test(num1) && !reg.test(num2)){
  4.         return num1 * num2;
  5.     }
  6.     var r1 = 0, r2 = 0, m;
  7.     var str1 = num1.toString(), str2 = num2.toString();
  8.     if(str1.indexOf('.')>-1){
  9.         r1 = str1.split('.')[1].length;
  10.     }
  11.     if(str2.indexOf('.')>-1){
  12.         r2 = str2.split('.')[1].length;
  13.     }
  14.     m = Math.pow(10,Math.max(r1,r2));
  15.     return (mul(num1,m) + mul(num2,m)) / m;
  16. }

乘法运算:

  1. function mul(num1,num2){
  2.         var reg = /\./i;
  3.     if(!reg.test(num1) && !reg.test(num2)){
  4.         return num1 * num2;
  5.     }
  6.     var len = 0, str1 = num1.toString(), str2 = num2.toString();
  7.     if(str1.indexOf('.')>=0){
  8.         len += str1.split('.')[1].length;
  9.     }
  10.     if(str2.indexOf('.')>=0){
  11.         len += str2.split('.')[1].length;
  12.     }
  13.     return Number(str1.replace('.','')) * Number(str2.replace('.','')) / Math.pow(10,len);
  14. }

除法运算:

  1. function div(num1,num2){
  2.         var reg = /\./i;
  3.     if(!reg.test(num1) && !reg.test(num2)){
  4.         return num1 * num2;
  5.     }
  6.     var len1 = 0, len2 = 0;
  7.     var str1 = num1.toString(), str2 = num2.toString();
  8.     //计算位数差
  9.     if(str1.indexOf('.')>-1){
  10.         len1 = str1.split('.')[1].length;
  11.     }
  12.     if(str2.indexOf('.')>-1){
  13.         len2 = str2.split('.')[1].length;
  14.     }
  15.     return mul(Number(str1.replace('.','')) / Number(str2.replace('.','')),Math.pow(10,len2-len1));
  16. }