【发布时间】:2016-08-31 18:32:48
【问题描述】:
我从其他 SO 问题中了解到的事情:
- 我必须使用整数或 Java 的 BigDecimal(Java 是我的例子,尽管问题更广泛),而不是浮点类型。
- 我必须至少比我想显示的小数位多存储一位。就我而言,我想显示 2 位小数。惯例是在数据库中使用小数(19,4)(在我的例子中是 Postgres,但这个问题更广泛)
当我在内存中有一个包含 101 个项目的账单,每个项目的成本为 1.00004999999999999 >
如果我在数据库中存储 4 位小数,每个项目将被四舍五入并存储为 1.0000 美元,当我从数据库中提取它们并将它们相加时,我得到 101.0000 美元,四舍五入为 101.00 美元。
如果我将存储精度提高到十进制 (19,5),我需要 1001 个项目而不是 101 个项目,但这仍然是可能的。它总是有可能发生,但一种可能的解决方案是大幅提高存储精度,使发生这种错误的可能性比闪电击中计算机的可能性小。
到目前为止,我的解决方案是永远不要使用 BigDecimal,而是始终使用 BigDecimal.setScale(4),它将其设置为 4 位小数。你会建议一种不同的方法吗?
我知道行不通的事情:
- 计算存储后的总数。我需要在用户输入数据时使用 JavaScript 计算它。
- 从不使用四舍五入的值进行计算。我不知道如何在不四舍五入的情况下存储它们
- 从不向上取整,总是向下取整。如果我的税值为 1.005049999,它必须显示为 1.01。这是一个商业规则。我可以挑战它,但必须有一种不影响业务运作方式的方法。
其他注意事项:
- 我不太关心执行速度或内存使用情况。
【问题讨论】:
-
您是否打算让您的系统支持价格为
1.00004999999999999精度?通过指定如此精确的价格,您似乎在自相矛盾,但在数据库中使用DECIMAL(19,4)。是哪一个? -
这是一个数学事实,round(a+b+c) 通常不等于round(a)+round(b)+round(c)。您必须根据业务规则决定哪一个给出正确的值。
-
我不编写会计软件,但我希望如果应用程序需要您进行舍入,它会要求您以特定应用程序的方式进行舍入。我>
-
只是想知道 - 保留超过 2 位十进制数字的货币是否有意义?我的意思是你不能去银行要求支付 0.0099 美元,要么是 1 美分,要么什么都没有......
-
@Kayaman 你是对的,我的错。我不想支持
1.0000499999999的个别价格。我对支持1.0000499999999的项目总数没有兴趣,但除非我将所有内容汇总起来,否则它们在内存中的价值。我所需要的只是准确地显示 2 位小数。DECIMAL(19,4)来自我理解的一种普遍接受的存储货币的解决方案。我可以对此引用几个 SO 答案。并不意味着他们是对的。