考虑Java中的以下代码:
String input = "33.3";
float num = Float.parseFloat(input);
System.out.printf("num: %f\n",num);
为什么输出上面的代码
num: 33.299999
?
不应该是
num: 33.300000
?
如果有人能向我解释,我真的很感激。
答案 0 :(得分:7)
您是浮点错误的受害者。在基数2中,33.3
在技术上是重复的二进制(类似于重复的十进制),就像m/n
m
和n
为整数而写gcd(m,n)=1
n
的素因子不是2的素因子的子集。这也意味着它不能写成有限数量的项m*(2^n)
的总和m
和n
是整数。
基数为10的7/6
也会出现类似的例子。
_
1.16
变为
1.16666667
然后按字面读取,并且不等于7/6。
答案 1 :(得分:3)
如果可以避免,请不要使用float
。这里的问题是%f
在没有那种精度的情况下将其视为双精度
String input = "33.3";
double num = Double.parseDouble(input);
System.out.printf("num: %f\n",num);
打印
33.300000
这是因为33.3f!= 33.3,float
精度较低。要查看实际值,您可以使用BigDecimal,它精确地覆盖实际值。
System.out.println("33.3f = " + new BigDecimal(33.3f));
System.out.println("33.3 = " + new BigDecimal(33.3));
打印
33.3f = 33.299999237060546875
33.3 = 33.2999999999999971578290569595992565155029296875
正如您所看到的,两种情况下所表示的真实值都略微过小。在%f
如何显示6个小数位的情况下,即使浮点数不准确到总共8个小数位。 double
精确到15-16位小数,因此除非值更大,否则您不会看到错误。例如一万亿或更多。
答案 2 :(得分:1)
问题在于浮点数具有有限的精度。
答案 3 :(得分:1)
32位浮点数包含足够的精度,大约精确到7位小数。 33.29999是小数点后7位。 将“输入”更改为3.3 - 您应该看到3.300000 将“输入”更改为333.3 - 您将看到如下内容:333.299988 使用64位浮点数可以提供更高的精度(15-17位小数)。