说说我对 javascript 浮点运算 BUG 的看法

对于 javascript 浮点运算 BUG 大家都应该有所耳闻,在网上也会收到很多解决办法,在这里我引用两篇博文。

Javascript 浮点运算问题分析与解决

Javascript优化后的加减乘除(解决js浮点数计算bug)

首先,用 2.1 / 0.335 举例说明我的观点。在计算器上计算会得到两组数值 6.26865671641791 和 6.2686567164179104477611940298507。

把 6.2686567164179104477611940298507 用  document.write(6.2686567164179104477611940298507+"<br>"); 在页面上输出会得到 6.268656716417911 数值更接近 6.26865671641791 数值。

所以我认为 javascript 浮点运算把精度控制在 14 位以内应该没什么问题,那么 toFixed 方法就可以满足要求。但是,你要是完全相信 toFixed 方法,你会发现并不是你想要的结果,四舍五入也有有问题。比如说,9.555.toFixed(2) 你会得到 9.55 。

综合网上的解决方案我的解决方案代码如下,希望有兴趣的朋友和我交流一下。看看有什么问题!

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>无标题文档</title>
  <style type="text/css">
    html, body { height: 100%; margin: 0px; padding: 10px; font: 12px/1.5 tahoma,arial, 'Hiragino Sans GB' ,\5b8b\4f53,sans-serif !important; vertical-align:baseline; }
  </style>
</head>
<body>
  <script type="text/javascript">
  //<![CDATA[
  Number.prototype.add=function(arg2) {
    var r1=0,r2=0,m,s1=this.toString(),s2=arg2.toString();
    if(s1.indexOf('.')!= -1)
      r1=s1.split('.')[1].length;
    if(s2.indexOf('.')!= -1)
      r2=s2.split('.')[1].length;
    m=Math.pow(10,Math.max(r1,r2));
    return ((this.mul(m))+(arg2.mul(m)))/m;
  };

  Number.prototype.sub=function(arg2) {
    var r1,r2,m,n,s1=this.toString(),s2=arg2.toString();
    if(s1.indexOf('.')!= -1)
      r1=s1.split('.')[1].length;
    if(s2.indexOf('.')!= -1)
      r2=s2.split('.')[1].length;
    m=Math.pow(10,Math.max(r1,r2));
    n=(r1>=r2)?r1:r2;
    return ((this.mul(m)-arg2.mul(m))/m).toFixed(n);
  };

  Number.prototype.mul=function(arg2) {
    var m=0,s1=this.toString(),s2=arg2.toString();
    if(s1.indexOf('.')!= -1)
      m+=s1.split('.')[1].length;
    if(s2.indexOf('.')!= -1)
      m+=s2.split('.')[1].length;
    return Number(s1.replace('.',''))*Number(s2.replace('.','')).div(Math.pow(10,m));
  };

  Number.prototype.div=function(arg2) {
    var t1=0,t2=0,r1,r2,s1=this.toString(),s2=arg2.toString();
    if(s1.indexOf('.')!= -1)
      t1=s1.split('.')[1].length;
    if(s2.indexOf('.')!= -1)
      t2=s2.split('.')[1].length;

    r1=Number(s1.replace('.',''));
    r2=Number(s2.replace('.',''));
    return (r1/r2)/Math.pow(10,t1-t2);
  };

  Number.prototype.toFixed=function(n) {
    var power=Math.pow(10,n)
       ,valuePower=this.mul(power)
       ,dotIndex=valuePower.toString().indexOf('.')
       ,afterFrist;
	   
    if(-1!=dotIndex)
      afterFrist=parseInt(valuePower.toString().substring(dotIndex+1,dotIndex+2));
    if(!isNaN(afterFrist)&&5<=afterFrist)
      valuePower+=0<this?1:-1;
		
    var fixed=parseInt(valuePower).div(power).toString();
    if(n==0)
      return fixed;
    if(fixed.indexOf('.')<0)
      fixed+='.';
    var padding=n+1-(fixed.length-fixed.indexOf('.'));
    for(var i=0;i<padding;i++)
      fixed+='0';
    return Number(fixed);
  };



  document.write(" 2.2 + 2.1  =  "+(2.2+2.1).toFixed(14)+"<br>");
  document.write(" 2.2 - 1.9  =  "+(2.2-1.9).toFixed(14)+"<br>");
  document.write(" 2.2  *  2.2  =  "+(2.2*2.2).toFixed(14)+"<br>");
  document.write("  -2.1  /  0.335 = "+(-2.1/0.335).toFixed(8)+"<br>");
  document.write(" 2.1 /  0.335  =  "+(2.1/0.335).toFixed(8)+"<br>");
  document.write(" 0.1 /  0.3   =  "+(0.1/0.3).toFixed(14)+"<br>");

  document.write("0.0999999999999999 * 0.05  = "+(0.0999999999999999*0.05).toFixed(14)+"<br>");
  document.write(6.2686567164179104477611940298507+"<br>");
  document.write(6.2686567164179104477611940298507.toFixed(14)+"<br>");
  
  document.write(9.555.toFixed(2)+"<br>");
  //]]>
  </script>
</body>
</html>


  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值