【发布时间】:2014-12-06 10:10:31
【问题描述】:
我正在调用一个截断方法来截断双精度值,以便小数点后应该有一个数字(不四舍五入),
对于前。 truncate(123.48574) = 123.4.
我的截断方法是这样的
public double truncate (double x) {
long y = (long) (x * 10);
double z = (double) (y / 10);
return z;
}
除了这个奇怪的输出之外,它几乎适用于所有值。
double d = 0.787456;
d = truncate(d + 0.1); //gives 0.8 as expected. Okay.
但是,
double d = 0.7;
d = truncate(d + 0.1); //should also give 0.8. But its giving 0.7 only.
//Strange I don't know why?
事实上它适用于所有其他 0.1、0.2、0.3、0.4、0.5、0.6、-、0.8、0.9
我的意思是,例如,
double d = 0.8;
d = truncate(d + 0.1); //gives 0.9 as expected
我也试过BigDecimal。但是一样。不用找了。
这是它的代码。
double d = 0.7;
BigDecimal a = new BigDecimal(d + 0.1);
BigDecimal floored = a.setScale(1, BigDecimal.ROUND_DOWN);
double d1 = floored.doubleValue();
System.out.println(d1); //Still gives 0.7
再一次,真正的事实是它与Math.round 配合得很好。
public double roundUp1d (double d) {
return Math.round(d * 10.0) / 10.0;
}
所以如果我打电话给roundUp1d(0.7 + 0.1),它会按预期给出 0.8。但我不希望这些值被四舍五入,所以我不能使用它。
0.7 有什么问题?
【问题讨论】:
-
我已经测试过了,如果你的输入是0.7+0.1,那么它会被错误计算到0.799999999999999
-
0.7 不能准确地用双精度表示,因此转换为双精度的 BigDecimal 可能仍会出现相同的“问题”。你知道基本问题吗?必填链接:What every programmer should know about Floating Point
-
当您执行
new BigDecimal(0.7).add(new BigDecimal(0.1))时会发生什么?您当前的BigDecimal代码不起作用,因为d + 0.1仍然是常规的double加法,它会为您提供浮点异常。 顺便说一句,它的拼写很奇怪而不是奇怪。 -
啊,是的,感谢@Tom。应该是
BigDecimal a = BigDecimal.valueOf(d).add(BigDecimal.valueOf(0.1));。这将在内部将双打转换为字符串(您不需要按照 Tom 的建议进行外部转换)。 -
这对所有人都有效吗...? 是的! 这确实是使用 BigDecimal 的全部意义 :) 但你需要使用它正确。简单地在您的代码中提及它并不构成正确的用法。我会发布一个答案。我在尝试教学时也学到了:D
标签: java double bigdecimal