首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >何时可以使用Java中的浮点数类型来进行货币计算?

何时可以使用Java中的浮点数类型来进行货币计算?
EN

Stack Overflow用户
提问于 2012-08-08 18:14:17
回答 5查看 1.2K关注 0票数 4

我了解到我不能使用浮点类型(float/double在Java中)来进行货币计算(以及需要精确结果时的任何其他计算)。我必须使用decimal数字类型(BigDecimal在Java中)。

现在我想我什么时候可以使用浮点类型。他们提供任何精确保证吗?假设我想用精确的0.001计算一些公式。如何知道是否可以使用浮点类型进行此计算?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-08-08 19:29:51

您可以在Java或其他语言中使用浮点类型,当您可以证明这些结果对于您的应用程序是可以接受的。

使用BigDecimal本身并不能解决这个问题。例如,假设一个银行账户包含87.34美元,并且必须加上一个月的利息,年利率为2.37%。首先,BigDecimal无法正确计算月利率,因为您必须将2.37%除以12,而2.37/12 (或.0237/12)不能精确地以十进制表示。其次,即使BigDecimal确实正确计算了月利率,并正确计算了87.34美元的利息,但在将其加到余额中之前,您可能仍然需要将这一数额乘以几美分。该四舍五入的规则可能会在某些法律文件中指定,并且可能与BigDecimal的四舍五入不匹配。

十进制浮点和二进制浮点都能够精确地计算许多结果,比您在示例中建议的.001精度要精确得多。当以各种方式使用时,两者都能够产生重大错误。

因此,要使用浮点,必须了解类型可以表示的值、浮点操作中发生的错误、将要执行的操作以及应用程序所需的内容。通常,通过精心制作操作可以避免浮点错误.例如,您可以通过将金额缩放为整数值来处理货币(使用8734表示$87.34,而不是使用87.34表示87.34)。作为另一个例子,您可以证明来自几个操作的累积错误小于0.5%,因此您可以执行这些操作并将最终结果舍入最近的百分比,这将是正确的,因为错误的大小永远不会导致最终答案不正确。

票数 8
EN

Stack Overflow用户

发布于 2012-08-08 18:35:29

我了解到我不能使用浮点类型(Java中的浮动/双)来进行货币计算。

你不能用double准确地代表70万亿美元以上的资金。对于小于此值的值,可以使用doublelong而不出现错误(前提是使用适当的舍入)

一旦理解了舍入的需要,使用double的IMHO就更容易使用了。

然而,许多人觉得它容易出错,尤其是因为您不知道谁可能需要维护代码。使用BigDecimal将确保正确使用四舍五入,并为您提供许多关于其工作方式的选项。

许多人感到不安的是,即使是0.1也不能精确地表示,而且BigDecimal可以显示精确的表示(以及为什么您必须注意如何转换为BigDecimal)。

代码语言:javascript
复制
System.out.println(new BigDecimal(0.1));

版画

代码语言:javascript
复制
0.1000000000000000055511151231257827021181583404541015625

许多粗俗的使用

代码语言:javascript
复制
new BigDecimal(Double.toString(0.1))

或者类似的工作方式,但具有讽刺意味的是,它的准确性仅限于他们试图避免使用的toString方法。

一个更有效的方法是

代码语言:javascript
复制
BigDecimal.valueOf(0.1)

这样就避免了创建字符串的需要。

支持double的库将正确地显示这个数字,但是一旦执行计算,默认的循环可能是不够的。

代码语言:javascript
复制
System.out.println(0.1 * 3);

版画

代码语言:javascript
复制
0.30000000000000004

在这种情况下,你必须说出你期望的精确程度。假设你有美元和美分,你可以使用

代码语言:javascript
复制
System.out.printf("%.2f%n", 0.1 * 3); // round output to two decimal places

版画

代码语言:javascript
复制
0.30

找出不能再继续添加0.01的地方

代码语言:javascript
复制
for (double d = 1; d < Long.MAX_VALUE; d *= 2) {
    long l = Double.doubleToLongBits(d);
    double d1 = Double.longBitsToDouble(l + 1);
    if (d1 - d > 0.01) {
        System.out.println("Cannot represent " + d + " plus 0.01");
        double d_1 = Double.longBitsToDouble(l - 1);
        if (d - d_1 < 0.01)
            System.out.println("Can represent " + d + " minus 0.01");
        break;
    }
}

版画

代码语言:javascript
复制
Cannot represent 7.0368744177664E13 plus 0.01
Can represent 7.0368744177664E13 minus 0.01
票数 4
EN

Stack Overflow用户

发布于 2012-08-08 19:01:28

假设我想计算一些精度为0.001的公式。如何知道是否可以使用浮点类型进行此计算?

浮点类型是基-2,而不是基-10。1/(10^n)不能用(二进制)浮点数精确表示,就像1/3不能精确地用十进制数表示一样。浮点数字对于科学类型的计算是有用的,因为这些数值可能是大的,也可能是小的,而测量的不确定度使计算机的精度限制相形见绌。在支持浮点运算的硬件上,浮点运算是相当快的,而其他非整数类型的运算则不那么快。

浮点数之所以被称为浮点数,是因为分数点两边的数字数将根据数字的不同而变化。浮点数字实质上表示为+/- 1.a * 2^b,其中ab是基-2数字。这类似于基于十进制的科学符号 1.a * 10^b。有关IEEE 754浮点数的更多信息,请参见维基百科文章。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11870621

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档