正负值四舍五入?

问题描述 投票:0回答:3

我正在尝试构建一个可以为正值和负值返回正确舍入的函数。

这是我的要求

Input       Output
-1.8550     -1.86
1.8550       1.86
-1384.8540   -1384.85
1384.8540     1384.85
-1384.8550   -1384.86
-1384.8560   -1384.86
-3203.8640   -3203.86 

我尝试了下面,但它不起作用。!

var customRoundOff = function(value) {
  debugger;
  var valueSign = Math.sign(value);
  var numericalPart = Math.abs(Number((value + "").split(".")[0]));
  var decPart = (value + "").split(".")[1];

  if (decPart && numericalPart) {
    var pntedDecimal = Number('0.' + decPart);
    var roundedDecimal = pntedDecimal.toFixed(2);
    var roundedValue = numericalPart + roundedDecimal;
    
    console.log("pntedDecimal", pntedDecimal);
    console.log("roundedDecimal", roundedDecimal);
    console.log("numericalPart", numericalPart);
    console.log("roundedValue", roundedValue);
    
    return roundedValue * valueSign; // Returns float
  } else {
    return value.toFixed(2); // Returns string
  }
}

customRoundOff(-1.8550);

javascript rounding
3个回答
2
投票

您需要添加少量金额才能四舍五入到下一位数字。

这是必要的,因为

toFixed
0.006
舍入到
0.01
,而不是
0.005
00.1

const
    round = n => {
        const sign = Math.sign(n);
        return sign * (Math.abs(n) + 0.000999999999).toFixed(2);
    },
    values = [-1.8550, 1.8550, -1384.8540, 1384.8540, -1384.8550, -1384.8560, -3203.8640];
    
console.log(...values.map(round));

更好的方法不进行调整(浮点数学是否被破坏?的怪癖),而是采用字符串,就像您已经拥有的那样。

const
    round = n => {
        let sign = Math.sign(n),
            [i, [...f]] = ((Math.abs(n)).toString() + '.').split('.');
            
        if (f.length > 2 && +f[2] >= 5) {
            let j = 2;
                c = 1;
            while (c && j--) {
               f[j] = f[j] === '9'
                   ? '0'
                   : +f[j] + c--;
               
            }
            if (c) i = (+i + 1);
        }
        return sign * i + '.' + f.slice(0, 2).join('');
    },
    values = [9.995, 0.004, 0.005, -1.8550, 1.8550, -1384.8540, 1384.8540, -1384.8550, -1384.8560, -3203.8640];

console.log(...values.map(round));


0
投票

另一种选择是如果

Intl.NumberFormat
输出不成问题,则使用
string

const arrNumbers=[-1.8550 ,1.8550, -1384.8540, 1384.8540, -1384.8550, 1384.8550, -3203.8640];

for (var i=0 ; i<arrNumbers.length; i++){
    console.log(
      new Intl.NumberFormat('en-US', { maximumFractionDigits: 2 }).format(arrNumbers[i])
    )
}


0
投票

我现在知道什么是错误,用一个简单的

+n.toFixed(2)

它为前两个测试用例返回错误值

-1.8550
1.8550
!!!

const
    round = n => {
        const sign = Math.sign(n);
        return sign * (Math.abs(n) + 0.000999999999).toFixed(2);
    },
    rnd = n => +n.toFixed(2),
    values = [-1.8550, 1.8550, -1384.8540, 1384.8540, -1384.8550, -1384.8560, -3203.8640];
    
console.log(JSON.stringify(values.map(round)));  // Nina's solution
console.log(JSON.stringify(values.map(rnd)));    // mine --> **wrong**

然而,

.toFixed()
错误并不像我最初担心的那么根本。这基本上是 JavaScript 中浮点数精度有限的另一种表现,请参阅here了解更多详细信息。

仔细观察问题时,我们发现以下内容:

const round = n => {
   const sign = Math.sign(n);
   return sign * (Math.abs(n) + 0.000999999999).toFixed(2);
  },
  rnd = n => +n.toFixed(2);

[-1.85500001,-1.855, 
 -1.85499999].forEach(v=>
 console.log(v,round(v),rnd(v))
);  

因此,Nina 的说法“

.toFixed(2)
0.006
切换到
0.01
”需要更正为:“
.toFixed()
0.00500000000001
(或上面
0.005
上类似的少量)切换到
0.01
”。尽管她在
round()
中的方法是正确的,但添加到中间结果的 small 数字
0.000999999999
需要明显更小。 比如:
0.000000000001
.

© www.soinside.com 2019 - 2024. All rights reserved.