爪哇奇怪的地板圆整
Possible Duplicate:
Moving decimal places over in a double
我在Java中遇到了一个奇怪的问题,我有以下代码:
double velocity = -0.07;
System.out.println("raw value " + velocity*200 );
System.out.println("floored value " + Math.floor(velocity*200) );
我有以下输出:
raw value -14.000000000000002
floored value -15.0
那些轨道0002把一切都搞砸了,顺便说一句,轨道2不应该存在,我认为它应该是小数点后的所有零,我能去掉那个2吗
更新:谢谢你们的帮助,伙计们,你们知道在不调用doubleValue方法的情况下对BigDecimal对象进行地板舍入的方法吗
# 1 楼答案
从The Floating-Point Guide:
如果需要与特定期望值相加的数字,则不能使用
double
。有关详细信息,请阅读链接到站点的链接# 2 楼答案
Java Double遵循IEEE 754浮点算法,它不能无限精确地表示每个实数。这次围捕是正常的。你不能在内部表现中摆脱它。当然可以使用字符串。格式化以打印结果
# 3 楼答案
使用BigDecimal。。。上面的问题是一个众所周知的舍入问题,在内存有限的计算机上使用表示方案。问题在于,答案在二进制(即基数2)系统中是重复的(如1/3=0.33333333…带十进制),无法正确表示。一个很好的例子是1/10=0.1,即0.000110011。。。二进制的。在某一点之后,1和0必须结束,从而导致感知错误
希望你不是在做对生活至关重要的事情。。。例如http://www.ima.umn.edu/~arnold/disasters/patriot.html。28人因舍入错误而丧生
# 4 楼答案
因为
floor(-14.000000000000002)
确实是-15
你看,
floor
被定义为小于或等于参数的最大整数。由于-14.000000000000002
不是一个整数,向下最接近的整数是-15
好了,现在让我们弄清楚为什么
-0.07 * 200
不完全是-14
。这是因为浮点数的内部表示是以2
为基数的,因此分母不是2
幂的分数不能以100%的精度表示。(与您不能将1/3表示为小数位数有限的小数点相同。)因此velocity
的值并不完全是-0.07
。(当编译器看到常量-0.07
时,它会用一个非常接近-0.07
但实际上不等于的二进制分数悄悄地替换它。)这就是为什么velocity * 200
并不完全是-14