JavaScript-0.5时四舍五入

我遇到的问题是Javascript在达到0.5时舍入数字的方式.
我正在编写征费计算器,并注意到结果之间存在0.1c的差异.

问题在于它们的结果为21480.705,我的申请将其转换为21480.71,而关税则为21480.70.

这是我用Javascript看到的内容:

(21480.105).toFixed(2)
"21480.10"
(21480.205).toFixed(2)
"21480.21"
(21480.305).toFixed(2)
"21480.31"
(21480.405).toFixed(2)
"21480.40"
(21480.505).toFixed(2)
"21480.51"
(21480.605).toFixed(2)
"21480.60"
(21480.705).toFixed(2)
"21480.71"
(21480.805).toFixed(2)
"21480.81"
(21480.905).toFixed(2)
"21480.90"

问题:

这种不稳定的路由到底是怎么回事?
获得“四舍五入”结果的最快方法是什么(当达到0.5时)?

解决方法:

因此,正如其他一些人已经解释的那样,“不规则”舍入的原因是浮点精度问题.您可以使用JavaScript数字的toExponential()方法进行调查.

(21480.905).toExponential(20)
#>"2.14809049999999988358e+4"
(21480.805).toExponential(20)
#>"2.14808050000000002910e+4"

如您在此处看到的21480.905,它得到的双精度表示形式比21480.905稍小,而21480.805得到的双精度表示形式则稍大于原始值.由于toFixed()方法使用双重表示形式,并且不知道您的原始预期值,因此它会尽一切可能并且应该使用其拥有的信息.

解决此问题的一种方法是,通过乘法将小数点移至所需的小数位数,然后使用标准Math.round(),然后通过除法或乘以反数再次将小数点移回.最后,我们调用toFixed()方法以确保输出值正确地补零.

var x1 = 21480.905;
var x2 = -21480.705;

function round_up(x,nd)
{
  var rup=Math.pow(10,nd);
  var rdwn=Math.pow(10,-nd); // Or you can just use 1/rup
  return (Math.round(x*rup)*rdwn).toFixed(nd)
}
function round_down(x,nd)
{
  var rup=Math.pow(10,nd);
  var rdwn=Math.pow(10,-nd); 
  return (Math.round(x*-rup)*-rdwn).toFixed(nd)
}

function round_tozero(x,nd)
{
   return x>0?round_down(x,nd):round_up(x,nd) 
}



console.log(x1,'up',round_up(x1,2));
console.log(x1,'down',round_down(x1,2));
console.log(x1,'to0',round_tozero(x1,2));

console.log(x2,'up',round_up(x2,2));
console.log(x2,'down',round_down(x2,2));
console.log(x2,'to0',round_tozero(x2,2));

最后:
遇到这样的问题通常是坐下的好时机,请您仔细考虑一下您是否实际使用了正确的数据类型来解决问题.由于浮点错误会随着迭代计算而累积,并且由于人们有时对在CPU中神奇消失/出现的货币敏感,所以您最好将货币计数器保持在整数“分”(或其他一些经过深思熟虑的货币)中结构),而不是浮点“美元”.

注意:

如果上述解决不了问题可以使用第二种方法

修改toFixed()的原型方法
Number.prototype.toFixed=function (d) { 
  var s=this+""; 
  if(!d)d=0; 
  if(s.indexOf(".")==-1)s+="."; 
  s+=new Array(d+1).join("0"); 
  if(new RegExp("^(-|\\+)?(\\d+(\\.\\d{0,"+(d+1)+"})?)\\d*$").test(s)){
      var s="0"+RegExp.$2,pm=RegExp.$1,a=RegExp.$3.length,b=true;
      if(a==d+2){
          a=s.match(/\d/g); 
          if(parseInt(a[a.length-1])>4){
              for(var i=a.length-2;i>=0;i--){
                  a[i]=parseInt(a[i])+1;
                  if(a[i]==10){
                      a[i]=0;
                      b=i!=1;
                  }else break;
              }
          }
          s=a.join("").replace(new RegExp("(\\d+)(\\d{"+d+"})\\d$"),"$1.$2");

      }
      if(b)s=s.substr(1); 
      return (pm+s).replace(/\.$/,"");
  }
  return this+"";
 
}
 结果:
0.735*25441=18699.14
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值