考虑以下 Java 代码:
String input = "33.3";
float num = Float.parseFloat(input);
System.out.printf("num: %f\n",num);
为什么上面代码的输出
num: 33.299999
?
难道不应该
num: 33.300000
?
如果有人可以向我解释这一点,我将不胜感激。
考虑以下 Java 代码:
String input = "33.3";
float num = Float.parseFloat(input);
System.out.printf("num: %f\n",num);
为什么上面代码的输出
num: 33.299999
?
难道不应该
num: 33.300000
?
如果有人可以向我解释这一点,我将不胜感激。
你是浮点错误的受害者。在基数 2 中,33.3
在技术上是重复的二进制(类似于重复的小数),当写成m/n
和是整数和m
时, 的素因数不是 2 的素因数的子集。这也意味着它不能写作为有限数量的项之和,其中和是整数。n
gcd(m,n)=1
n
m*(2^n)
m
n
类似的例子发生7/6
在以 10 为底的情况下。
_
1.16
变成
1.16666667
然后按字面意思阅读,不等于 7/6。
float
如果可以避免,请不要使用。这里的问题是,%f
当它没有那么精确时,将其视为双精度
String input = "33.3";
double num = Double.parseDouble(input);
System.out.printf("num: %f\n",num);
印刷
33.300000
这是因为 33.3f != 33.3 asfloat
的精度较低。要查看实际值,您可以使用精确覆盖实际值的 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 位,因此除非值更大,否则您不会看到错误。例如一万亿或更多。
32 位浮点数包含大约 7 个小数位精度的足够精度。33.29999 是小数点后 7 位。将“输入”更改为 3.3——你应该看到 3.300000 将“输入”更改为 333.3——你会看到类似:333.299988 使用 64 位浮点数会给你更高的精度(15-17 位小数)。
问题很简单,浮点数的精度是有限的。