此代码无法正常工作。
a=-1;
b=0.1;
for(i=0;i<=20;i++){
System.out.println(i + ". x= " + a);
a=a+b;
}
在控制台上我应该看到:
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
...等
但这就是发生的事情:
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
我在这里做错了什么?
答案 0 :(得分:4)
这里有什么浮点不准确。由于double
的精度有限,因此无法精确表示所有十进制数。特别是0.1
是一个重复的二进制文件,因此所有有限长度的二进制表示将是不准确的。这意味着计算机无法存储您正在使用的数字。
您可以通过格式化输出来修复输出(例如System.out.format("%d. x=%.1f", i, a);
),也可以使用BigDecimal
代替double
来修正数字。或者,您可以通过每次计算a
而不是累积(并且每次都添加增量错误)来减少问题的规模,例如, a = i/10.0
。这取决于你想要达到的目标。
重要的“带回家信息”是不能依赖双打来提供完整准确的答案,你应该期待浮点运算中的小错误。
答案 1 :(得分:2)
答案 2 :(得分:2)
答案 3 :(得分:1)
我最喜欢的是使用System.out.printf()
就像它的C对应物一样,你定义了你要传递给它的变量的类型,然后就把它变成了那种类型的东西。例如
System.out.printf("%.1f", yourDouble);
应该做的伎俩。
答案 4 :(得分:0)
您可能正在为每个对象使用整数。相反,当你去显示它们时,首先调用这个方法:
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();
}
或者使用正确类型的对象而不是整数...
答案 5 :(得分:0)
使用String.format或者只是在system.out.println中使用十进制格式化语法,你应该看到你想要的东西。 浮点运算以不同的方式在内部表示。因此,对这些值的简单打印并不总是让您希望您需要屏幕视图格式的内容。