java Float 和 BigDecimal 精度差异
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11557839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Float and BigDecimal precision difference
提问by
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);
}
RESULT:
3.1
3.0999999046325684
Why they are different result? I am using JDK1.7.0_03
结果:
3.1
3.0999999046325684
为什么他们是不同的结果?我使用的是 JDK1.7.0_03
采纳答案by dacwe
3.1
defines a double
while 3.1f
defines a float
. What you see is the problem the float
has of representing that value (float uses "only" 32-bits and double 64-bits).
3.1
定义了一个double
while3.1f
定义了一个float
。您看到的是float
表示该值的问题(浮点数“仅”使用 32 位和双 64 位)。
If you want to define a 3.1
exactly using BigDecimal
use the String
constructor:
如果你想定义一个3.1
完全BigDecimal
使用的String
构造函数:
BigDecimal foo = new BigDecimal("3.1");
System.out.println(foo);
Output:
输出:
3.1
回答by Peter Lawrey
float
and double
are different types with different precisions.
float
并且double
是具有不同精度的不同类型。
BigDecimal.valueOf(double) can correct for the representation error in double
but not that in float
BigDecimal.valueOf(double) 可以纠正 indouble
但不能纠正表示错误float
IMHO don't use float
unless you have a veryreason to do so.
恕我直言,不要使用float
,除非你有非常的理由这样做。
回答by Matt
The problem is that for both float and double, you are using 32 and 64 bits respectively for representation of both the integer and decimal part of the number. The problem comes in when you try to represent a fractional value which doesn't really have an accurate decimal representation in binary bits.
问题是,对于 float 和 double,您分别使用 32 位和 64 位来表示数字的整数部分和小数部分。当您尝试表示一个小数值时,问题就出现了,而该小数值在二进制位中实际上没有准确的十进制表示。
Take .1 for example, there's no way to exactly represent this in base 2, any more than there is a way to accurately represent 1/3 in base 10.
以 0.1 为例,没有办法在基数 2 中准确表示它,就像有一种方法可以在基数 10 中准确表示 1/3。
So java uses some tricks so that when you say:
所以java使用了一些技巧,所以当你说:
float f = 3.1;
System.out.println(f);
It prints out the right number. However, when you start doing arithmetic with these values, you end up with rounding errors.
它打印出正确的数字。但是,当您开始使用这些值进行算术运算时,最终会出现舍入错误。
BigDecimal is accurate because it uses a different representation. It internally stores a BigInteger (which uses an int[] to represent huge numbers). It then uses a precision value to tell it how many of those integer digits are are after the decimal point.
BigDecimal 是准确的,因为它使用不同的表示。它在内部存储一个 BigInteger(它使用一个 int[] 来表示巨大的数字)。然后它使用一个精度值来告诉它有多少整数位在小数点后。
For instance, the value 3.1 would be represented in a BigDecimal as 31,precision=1 For this reason, BigDecimal doesn't suffer from the same rounding issues a float and double.
例如,值 3.1 在 BigDecimal 中将表示为 31,precision=1 出于这个原因,BigDecimal 不会遇到相同的舍入问题,即浮点数和双精度数。
However, when you use a float/double value to initialize a BigDecimal, the same rounding error makes it's way into the BigDecimal instance. That's why it's recommended to use a String to construct the value.
但是,当您使用浮点/双精度值来初始化 BigDecimal 时,同样的舍入错误会使其进入 BigDecimal 实例。这就是为什么建议使用 String 来构造值的原因。
回答by Jay Patel
I had a similar issue due to a rookie mistake which I wanted to share:
由于我想分享的菜鸟错误,我遇到了类似的问题:
BigDecimal bd = new BigDecimal(float);
This was giving that extra precision I didn't want and setting it to String fixed it...
这提供了我不想要的额外精度并将其设置为 String 修复它......
However, I was doing this:
但是,我是这样做的:
BigDecimal bd = new BigDecimal(float);
bd.setScale(2, RoundingMode.HALF_UP);
Rookie Mistake. I should have done this.
菜鸟错误。我应该这样做。
bd = bd.setScale(2, RoundingMode.HALF_UP);