我正在向我的订单页面添加客户端小计计算,以便在用户进行选择时显示批量折扣。
我发现有些计算在这里或那里偏离了一美分。除了总数与最终计算的服务器端总数不匹配(在 PHP 中)之外,这并不是什么大问题。
我知道舍入误差是处理浮点数时的预期结果。例如,149.95 * 0.15 = 22.492499999999996 和 149.95 * 0.30 = 44.98499999999999。前者根据需要进行循环,后者则不需要。
我搜索了这个主题并找到了各种讨论,但没有一个能令人满意地解决这个问题。
我目前的计算如下:
discount = Math.round(price * factor * 100) / 100;
一个常见的建议是以美分而不是美元为单位工作。但是,这需要我转换我的起始数字,将它们四舍五入,将它们相乘,将结果四舍五入,然后再将其转换回来。
本质上:
discount = Math.round(Math.round(price * 100) * Math.round(factor * 100) / 100) / 100;
我正在考虑在四舍五入之前将数字加 0.0001。例如:
discount = Math.round(price * factor * 100 + 0.0001) / 100;
这适用于我尝试过的场景,但我想知道我的逻辑。添加 0.0001 是否总是足够,而且永远不会太多,以强制获得所需的舍入结果?
注意:出于我的目的,我只关心每个价格的单一计算(因此不会复合错误)并且永远不会显示超过两位小数。
编辑:例如,我想将 149.95 * 0.30 的结果四舍五入到小数点后两位并得到 44.99。但是,我得到 44.98,因为实际结果是 44.98499999999999 而不是 44.985。错误不是由/ 100
. 在那之前就已经发生了。
测试:
alert(149.95 * 0.30); // yields 44.98499999999999
因此:
alert(Math.round(149.95 * 0.30 * 100) / 100); // yields 44.98
考虑到乘法的实际结果,44.98 是预期的,但不是期望的,因为它不是用户所期望的(并且与 PHP 结果不同)。
解决方案:我要将所有内容都转换为整数来进行计算。正如公认的答案所指出的,我可以稍微简化我原来的转换计算。我添加 0.0001 的想法只是一个肮脏的黑客。最好为工作使用正确的工具。