代码:
class Main {
public static void main (String[] args) {
System.out.print("float: ");
System.out.println(1.35f-0.00026f);
System.out.print("double: ");
System.out.println(1.35-0.00026);
}
}
输出:
float: 1.34974
double: 1.3497400000000002
???浮点数得到了正确的答案,但是双倍是从没有地方添加额外的东西,为什么?
不应该比浮动更精确吗?
答案 0 :(得分:10)
浮点数是4个字节宽,而双数是8个字节宽。
检查What Every Computer Scientist Should Know About Floating-Point Arithmetic
当然双精度具有更高的精度,因此它的舍入误差略小。
将无数多个实数压缩成有限数量的位 需要近似的表示。虽然有无限的 许多整数,在大多数程序中,整数计算的结果都可以 以32位存储。相反,给定任意数量的位, 大多数带有实数的计算都会产生数量 不能使用那么多位来精确表示。 因此 浮点计算的结果通常必须按顺序舍入 适应它的有限表示。这个舍入误差是 浮点计算的特征。
旁注: -
我建议如果你想要精确的十进制值,那么使用java.math.BigDecimal
答案 1 :(得分:3)
如果您对转换 double 值的规则有所了解 到字符串,由 Double.toString [Java-API]的文档指定,您知道该程序打印的最小小数足以区分double值 来自最近的邻居,前后至少有一位数字 小数点。
检查Joshua Bloch的 Java Puzzlers:陷阱,陷阱和角落案例 - 难题2:变革的时间。他在那一章解释了这个问题。
答案 2 :(得分:3)
这是因为浮点计算的数字机制。 此外,当java尝试打印浮点值时,它会截断尾随零。 而且,您知道, double 类型使用8个字节而 float 使用4.因此 double 预设更大。
因此,当java计算你的浮点值时,它会得到类似1.3497400的东西并在输出之前截断它。 当java计算你的double值时,它会得到更多的数字,所以你得到了这样的结果。
尝试执行此简单示例以便更好地理解:
public class Test {
public static void main( String[] args ) {
float sum = 0;
for (int i = 1; i <= 10; i++) {
sum += 0.1;
}
System.out.println( sum );
}
}
public class Test {
public static void main( String[] args ) {
double sum = 0;
for (int i = 1; i <= 10; i++) {
sum += 0.1;
}
System.out.println( sum );
}
}