int和double除以双java

时间:2014-01-08 19:34:07

标签: java double ieee-754

我如何解释以下内容:

    double o = 2.3;
    int i = (int) (o * 100000.0);
    double d = i / 100000.0;
    System.out.println(d);

打印2.29999

    double o = 2.3;
    double i = o * 100000.0;
    double d = i / 100000.0;
    System.out.println(d);

打印2.3

将int除以double时,java首先将int转换为double,然后进行除法 - 如果是这样,两个代码块应该有效地打印相同的值吗?

似乎有一些我缺少的IEEE 754浮点精度规范和/或内联的jvm优化

 double i = 2.3 * 100000.0;
 double d = i / 100000.0;

如      double d = 2.3 * 100000.0 / 100000.0; 有效地取消了分裂并使其成为无操作。

思想?

3 个答案:

答案 0 :(得分:9)

2.3在IEEE-754 64位二进制浮点中不能完全表示。您的第一个代码序列中会发生什么:

  • 源文本2.3将转换为最接近的可表示值,2.29999999999999982236431605997495353221893310546875。
  • 将其乘以100000的确切数学结果也不完全可以表示,因此它舍入为229999.99999999997089616954326629638671875。
  • 当转换为int时,转换会截断,产生229999。
  • 再分为100000轮,产生2.29999000000000020094148567295633256435394287109375。
  • 打印上述内容时,Java会将其显示为“2.29999”。

答案 1 :(得分:4)

  

似乎有一些我缺少的IEEE 754浮点精度规范

当你使用(int)时,它会截断小数部分,无论它与下一个整数值有多接近。由于信息丢失,这是不可逆的,所以你不会得到相同的结果也就不足为奇了。

您可以做的是以下

double o = 2.3;
long l = Math.round(o * 100000.0);
double d = l / 100000.0;
System.out.println(d);
  

内联的jvm优化......使其成为无操作

JVM可能会对其进行优化,但不会更改结果。如果优化改变了结果,则它是优化器中的错误。

答案 2 :(得分:1)

double i = o * 100000.0;

此后i的值为229999.99999999997(您可以通过添加简单的打印声明自行查看;这是由于floating-point inaccuracies)。

int i = (int) (o * 100000.0);

此后i的值为229999(即由于int演员而导致小数部分被截断的上述值。)

因此,在行

double d = i / 100000.0;

您在两个片段中使用两个数值不同的i值(即它们相差约1),因此输出不同。

正确的说法是,当将int除以double时,int首先转换为double(这是通过字节码指令i2d完成的)。