我正在尝试构建一个可以为正值和负值返回正确舍入的函数。
这是我的要求
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);
您需要添加少量金额才能四舍五入到下一位数字。
这是必要的,因为
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));
另一种选择是如果
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])
)
}
我现在知道什么是错误,用一个简单的
+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
.