5

可能的重复:
在 java 中使用 Doubles 保持精度

你知道Java中这两种操作的区别吗?

final double m1 = 11d / 1e9; // gives 1.1e-8
final double m2 = 11d * 1e-9; // gives 1.1000000000000001e-8

我在生成的字节码中看到 m2 的预编译结果已经不是我所期望的。
javap -verbose -c我的输出中可以看到以下值:

const #3 = double   1.1E-8d;
[...]
const #6 = double   1.1000000000000001E-8d;

当我在其他表达式中使用 m1 或 m2 时,我没有相同的结果。

当我在 C 中尝试同样的事情时,m1 和 m2 严格来说是 1.1e-8

我认为我的问题在于 java 处理双精度计算的方式,但我无法解释自己错过了什么。

4

3 回答 3

3

Java 和 C 没有区别,都尊重 IEEE 浮点标准。唯一的区别可能是您打印它的方式。确切的数字 1.1e-8 不能表示为double. 输出的差异可能归因于有关表示误差如何累积的细节,以及用于打印结果的舍入方式。

于 2012-07-16T11:43:45.647 回答
1

您所拥有的区别在于 1e9 是完全可表示的,而 1e-9 是不完全可表示的。一个小的表示错误会导致您可以看到的算术错误。

System.out.println(new BigDecimal(1e9));
System.out.println(new BigDecimal(1e-9));

印刷

1000000000
1.0000000000000000622815914577798564188970686927859787829220294952392578125E-9

区别不在于您是否使用过,*或者/您在一种情况下使用了整数,而在另一种情况下使用了分数。

System.out.println(11 * 1e9);
System.out.println(11 * 1e-9);

印刷

1.1E10
1.1000000000000001E-8
于 2012-07-16T12:02:37.163 回答
0

如果您使用 BigDecimal 如下:

BigDecimal a=new BigDecimal(1e-9);
BigDecimal b=new BigDecimal(11);
System.out.println(a.multiply(b).toString());

你会看到你的号码是

1.10000000000000006850975060355784206078677556206457666121423244476318359375E-8

JVM 将您的数字四舍五入并将其更改为:

1.1000000000000001e-8
于 2012-07-16T12:01:11.590 回答