在Java中将Java打印到System.out

Printing Java doubles to System.out in Java

本问题已经有最佳答案,请猛点这里访问。

这段代码没有按我想象的那样工作。

1
2
3
4
5
6
a=-1;  
b=0.1;  
for(i=0;i<=20;i++){  
    System.out.println(i +". x=" + a);  
    a=a+b;  
}

在控制台上,我应该看到:

1
2
3
4
5
6
7
8
0. x= -1.0  
1. x= -0.9  
2. x= -0.8  
3. x= -0.7  
4. x= -0.6  
5. x= -0.5  
6. x= -0.4  
7. x= -0.3

……等

但事情是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
0. x= -1.0  
1. x= -0.9  
2. x= -0.8  
3. x= -0.7000000000000001  
4. x= -0.6000000000000001  
5. x= -0.5000000000000001  
6. x= -0.40000000000000013  
7. x= -0.30000000000000016  
8. x= -0.20000000000000015  
9. x= -0.10000000000000014  
10. x= -1.3877787807814457E-16  
11. x= 0.09999999999999987  
12. x= 0.19999999999999987  
13. x= 0.2999999999999999  
14. x= 0.3999999999999999  
15. x= 0.4999999999999999  
16. x= 0.5999999999999999  
17. x= 0.6999999999999998  
18. x= 0.7999999999999998  
19. x= 0.8999999999999998  
20. x= 0.9999999999999998

我在这里做错什么了?


你这里的是浮点误差。由于double的精度有限,它们不能精确地表示所有的十进制数。尤其是0.1是一个循环的二进制,因此所有有限长度的二进制表示都将不准确。这意味着计算机无法准确存储您使用的数字。

您可以通过格式化(如System.out.format("%d. x=%.1f", i, a);)来修复输出,也可以使用BigDecimal而不是double来修复数字。或者,您可以通过每次计算a来减少问题的规模,而不是累积(并每次增加一个增量错误),例如a = i/10.0。这取决于你想要达到的目标。

重要的"带回家的信息"是不能依靠双精度来给出完全准确的答案,而且您应该期望浮点运算中出现小的错误。


尝试格式化输出:

1
2
3
4
for(i=0;i<=20;i++){  
    System.out.format("%d. x=%.1f", i, a);  
    a=a+b;  
}

有关格式化输出的更多信息,请参阅文档


需要精度时:用BigDecimal代替double

有关更多详细信息,请参阅此问题:Double与BigDecimal?

编辑:如果不需要精度,可以格式化输出。


我个人最喜欢使用System.out.printf()。< BR>就像它的C对应物一样,你定义了你要传递给它的变量的类型,然后把它扔到一个类似的类型。例如埃多克斯1〔10〕

应该有技巧。

资源:打印备忘单


在system.out.println中使用string.format或pain十进制格式语法,您应该看到您想要的内容。浮点运算的内部表示方式不同。因此,这种值的简单打印并不总是给你想要的屏幕视图格式的中间。


您可能正在为每个这些对象使用int。相反,当您要显示它们时,请先调用此方法:

1
2
3
4
5
6
7
public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    BigDecimal bd = new BigDecimal(value);
    bd = bd.setScale(places, BigDecimal.ROUND_HALF_UP);
    return bd.doubleValue();
}

或者使用正确的对象类型而不是ints…