【发布时间】:2017-09-02 12:59:57
【问题描述】:
我们正在用 Javascript 构建一个表,其中 Handsontable 表示货币金额。我们为用户提供了以两位小数或无小数位呈现金额的可能性(这是客户的要求)。然后我们发现这样的事情:
Column A Column B Column C = A + B
-------------------------------------------
-273.50 273.50 0 Two decimals
-273 274 0 No decimals
调查了一下,发现Javascript中基本的舍入函数,Math.round(),works like this:
如果小数部分正好是 0.5,则参数将四舍五入到 +∞ 方向上的下一个整数。 请注意,这与许多语言的
round()函数不同,后者通常将这种情况舍入到 远离零的下一个整数,而不是(在以下情况下给出不同的结果小数部分正好为 0.5 的负数)。
当我们处理货币金额时,我们不关心小数点后第二位之后会发生什么,因此我们选择将 -0.0000001 添加到表中的任何负值。因此,当渲染有两位或没有小数的值时,现在我们得到了正确的结果,因为Math.round(-273.5000001) = -274,而Math.round(-273.4900001) 仍然是 -273。
尽管如此,我们希望找到一个更好的解决方案来解决这个问题。那么实现这一点的最好、最优雅的方法是什么(不需要修改原始数值)?请注意,我们不直接调用Math.round(x),我们只是告诉 Handsontable 用给定的小数位数格式化一个值。
【问题讨论】:
-
var rounded = (val < 0) ? Math.round(val - 0.5) : Math.round(val+0.5); -
实际上,在处理货币时,您应该只使用最小面额的整数值。添加小数点只是为了显示。这将防止该区域的计算出现很多问题。
-
@Sirko 这是一个有趣的观点,但是如果我们有 -27350 美分的欧元(以最小面额保存),当我要在欧元面额中显示没有小数位时,我仍然会将 -273 作为显示的值,因为我之前必须将该值除以 100。
-
[33, 2.3, 53.34].map(x=>x.toFixed(2)).join(", ") == "33.00, 2.30, 53.34"因此您只需要.toFixed(2) -
@CarlosAlejo 我没有建议这会解决手头的具体问题。这只是一个提示,在处理货币时可能会为您省去一些麻烦,因为浮点问题通常比其他计算更重要。
标签: javascript math rounding handsontable