我遇到的问题是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中,因此最好将货币计数器保持在整数“分”(或其他一些经过深思熟虑的货币)中结构),而不是浮点“美元”。

    10-06 14:21