浮点数和BigDecimal精度的区别

5
public static void main(String[] args) {
    // TODO Auto-generated method stub
    BigDecimal foo,foo1;
    foo=BigDecimal.valueOf(3.1);
    foo1=BigDecimal.valueOf(3.1f);

    System.out.println(foo);
    System.out.println(foo1);

}

结果:
3.1
3.0999999046325684

为什么这两个结果不同?我使用的是JDK1.7.0_03。


3
我可以帮您进行翻译。下面是您需要翻译的内容的中文版:http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html这篇文章介绍了计算机处理浮点数的基本原理和一些常见的问题。文章首先解释了浮点数的表示方法,包括符号、指数和尾数等部分,并讲述了浮点数的舍入和舍入误差。随后,文章讨论了一些在浮点数计算过程中可能出现的问题,如溢出、下溢、无穷大和NaN等。最后,文章给出了一些处理浮点数的实用技巧和建议。 - Mysticial
我建议阅读这个链接 - Keppil
可能是浮点运算不能产生精确结果的重复问题。 - Louis
2
可能是[浮点数计算存在问题吗?]的重复问题(https://dev59.com/G3RB5IYBdhLWcg3wj36c)。 - james.garriss
4个回答

5

3.1定义了一个double,而3.1f则定义了一个float。问题在于float无法准确表示该值(float只使用32位,而double使用64位)。

如果您想使用BigDecimal准确地定义一个3.1,请使用String构造函数:

BigDecimal foo = new BigDecimal("3.1");
System.out.println(foo);

输出:

3.1

那么,这是浮点数的问题还是Bug? 我应该使用double来避免Bug吗? - user1482015
3
OP,这些不是程序上的bug。请阅读其他人在你的问题下面提出的建议。对这些问题的认识是编程基础中的101。 - Marko Topolnik
话虽如此,最好的方法是使用 String 而不是 doublefloat - Louis Wasserman
谢谢大家,你们的回答对我都非常有帮助。但是我只能选择一个最佳答案。 我选择了dacwe的答案,因为我只是一个简单的程序员,知道如何解决问题已经足够了。 - user1482015

0

我曾经因为一个新手错误遇到了类似的问题,想要分享一下:

BigDecimal bd = new BigDecimal(float); 

这给了我额外的精度,而将其设置为字符串则解决了问题...

然而,我正在做这个:

BigDecimal bd = new BigDecimal(float);
bd.setScale(2, RoundingMode.HALF_UP);

新手错误。我应该做这个。

bd = bd.setScale(2, RoundingMode.HALF_UP);

0

floatdouble是具有不同精度的不同类型。

BigDecimal.valueOf(double)可以纠正double中的表示误差,但不能纠正float中的表示误差。

在我看来,除非你有一个非常好的理由,否则不要使用float


0
问题在于对于浮点数和双精度数,你分别使用32位和64位来表示数字的整数和小数部分。当你尝试表示一个在二进制位中没有准确十进制表示的分数值时,问题就出现了。
例如,以0.1为例,在基数2中无法准确表示它,就像在基数10中无法准确表示1/3一样。
因此,Java使用一些技巧,使得当你说:
float f = 3.1;
System.out.println(f);

它打印出正确的数字。然而,当你开始对这些值进行算术运算时,你会遇到舍入误差。

BigDecimal是准确的,因为它使用不同的表示方法。它在内部存储一个BigInteger(使用int[]来表示巨大的数字)。然后使用精度值告诉它有多少个整数位在小数点后面。

例如,值3.1将在BigDecimal中表示为31,精度=1。因此,BigDecimal不会像float和double一样受到相同的舍入问题的影响。

然而,当你使用float/double值来初始化BigDecimal时,相同的舍入误差会进入BigDecimal实例。这就是为什么建议使用字符串来构造值的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接