我对 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
稍小的 double 表示,而 21480.805
获得了稍大的 double 表示比原来的值(value)。由于 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 中异常敏感,也许您最好将货币计数器保持在整数“美分”(或其他一些经过深思熟虑的结构)而不是浮点“美元”。
关于javascript - 0.5时向上或向下舍入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55096050/