1

可能重复:
将小数位移动到双精度

我在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 搞砸了一切,顺便说一句,不应该有那个 traling 2,我认为它应该在小数点后全为零,我可以摆脱那个 2 吗?

更新:感谢您的帮助,伙计们,您知道有什么方法可以在 BigDecimal 对象上进行四舍五入而不调用 doubleValue 方法吗?

4

4 回答 4

4

因为floor(-14.000000000000002)确实是-15

你看,floor被定义为小于或等于参数的最大整数。由于-14.000000000000002不是整数,向下最接近的整数 -15

好吧,现在让我们弄清楚为什么-0.07 * 200不完全是-14. 这是因为浮点数的内部表示在 base 中2,因此分母不是 的幂的分数不能2以 100% 的精度表示。(就像您不能将 1/3 表示为小数位数有限的小数一样。)因此, 的值velocity不完全是-0.07. (当编译器看到常量-0.07时,它会默默地用一个非常接近-0.07但实际上不等于的二进制分数替换它。)这就是为什么velocity * 200不完全是-14.

于 2012-05-15T13:57:34.157 回答
3

来自浮点指南

为什么我的数字,比如 0.1 + 0.2 加起来不是很好的 0.3 轮,而是得到一个奇怪的结果,比如 0.30000000000000004?

因为在内部,计算机使用的格式(二进制浮点)根本无法准确表示 0.1、0.2 或 0.3 之类的数字。

当代码被编译或解释时,你的“0.1”已经被四舍五入到该格式中最接近的数字,这会在计算发生之前导致一个小的舍入误差。

如果您需要精确加起来等于特定预期值的数字,则不能使用double. 阅读链接到的网站了解详细信息。

于 2012-05-15T13:51:34.513 回答
2

使用 BigDecimal... 上面的问题是一个众所周知的舍入问题,它与有限内存计算机上使用的表示方案有关。问题是答案在二进制(即基数 2)系统中是重复的(即像 1/3 = 0.33333333... 带十进制)并且无法正确呈现。一个很好的例子是 1/10 = 0.1,即 0.000110011001100110011001100110011... 二进制。在某个点之后,1 和 0 必须结束,从而导致感知错误。

希望你不是在研究对生命至关重要的东西......例如http://www.ima.umn.edu/~arnold/disasters/patriot.html。28人因四舍五入而丧生。

于 2012-05-15T13:47:44.233 回答
1

Java double 遵循 IEEE 754 浮点算法,它不能以无限的精度表示每一个实数。这个轮回是正常的。您无法在内部表示中摆脱它。您当然可以使用 String.format 来打印结果。

于 2012-05-15T13:49:26.870 回答