JavaScript - 在什么操作之后需要toFixed()以及应该传递什么参数?

时间:2014-12-23 16:43:18

标签: javascript floating-point double floating-accuracy

在讨论herehere中,我们看到toFixed()可用于帮助维护使用二进制浮点数时的精度。

由于各种原因,我不想使用第三方库。但是,对于任何可以在64位内表示为有限小数的分数,我希望以最通用的方式保持最大精度。

假设我使用toFixed(),我什么时候需要使用它?并且有一个最好的"为了实现上述目标,我可以传递给它的论点?

例如,考虑JavaScript能够在不同操作后将1/10分数表示为有限小数:

10/100        = 0.1
0.09 + 0.01   = 0.09999999999999999
1.1 - 1       = 0.10000000000000009

第一步不需要修正步骤,而最后两步则不需要。此外,传递toFixed()值为15适用于此情况(例如:Number((0.09 + 0.01).toFixed(15))):

10/100        = 0.1
0.09 + 0.01   = 0.1
1.1 - 1       = 0.1

但是传递16不会:

10/100        = 0.1
0.09 + 0.01   = 0.1
1.1 - 1       = 0.1000000000000001

尝试JSFIDDLE

作为toFixed()的论据15会不会达到上述目标?更重要的是,我什么时候打电话给toFixed()?除了加,减,乘和除之外,我的数学例程还使用Math.pow()Math.exp()Math.log()

1 个答案:

答案 0 :(得分:0)

当可能发生不准确时重新开始:

除非深入了解IEEE-754双精度浮点的技术细节,并让您的代码根据其运行的两个值的特定特征进行定制,否则您将无法知道结果将是不准确的;任何操作,包括简单的添加,都可能导致不准确的结果(如着名的0.1 + 0.2 = 0.30000000000000004示例中所示)。

重新传入toFixed的数字:

您可以使用toFixed(然后转换回数字)进行四舍五入(就像您在问题中一样),但您应该使用的位数由结果中所需的精度决定,以及您正在使用的价值范围。从根本上说,您需要确定所需的精度,然后使用舍入来获得最高精度的精度,因为在整个值范围内使用IEEE-754浮点无法获得完美的精度(如你懂)。你总得到15位有效数字;你需要决定如何在小数的左边和右边分配它们。

但是说你的正常"值范围小于100亿,例如,小数点后四位或五位,您可以使用5,因为左边大约有10位数,右边大约有5位数。

以着名的例子为例:



function roundToRange(num) {
  return +num.toFixed(5);
}

snippet.log(roundToRange(0.1 + 0.2)); // 0.3, rather than the usual 0.30000000000000004

<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
&#13;
&#13;
&#13;

圆润的结果当然可能并不完美,因为在基数2(IEEE-754使用的)中,基本10个基数为10的整数基数都是不完美的,因此必须近似值,但是通过在您的范围内工作,您可以保持范围之外的不精确度不会增加(或乘以!)。