【问题标题】:Rounding away from zero in Javascript在 Javascript 中从零四舍五入
【发布时间】: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


【解决方案1】:

正如@dandavis 在 cmets 中指出的那样,处理此问题的最佳方法是使用 .toFixed(2) 而不是 Math.round()

Math.round(),正如您所说,四舍五入。

.toFixed() 将从零四舍五入。我们在其中指定2 来指示进行舍入时使用的小数位数。

【讨论】:

  • 我认为这是误导。 .toFixed() 不会从零四舍五入。它截断小数位。 (1.237).toFixed(2); // "1.23",否则您可能会期望 1.24
  • 它绝对远离 0,但它的行为与 C# 不同。剪切后剩余的绝对值在 JS 中必须 >5,而在 C# 中必须 >= 5。decimal.Round(1.255m, 2, MidpointRounding.AwayFromZero) // C# = 1.26 (1.255).toFixed(2) // JS = 1.25
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多