具有双值java的有限机器

use*_*446 0 java double

你能帮助我知道为什么我得到结果0.0吗?

我的代码:

public void rechneFunktion() {

    double x1 = Math.pow(10, 20);
    double x2 = 1223.0;
    double x3 = Math.pow(10, 18);
    double x4 = Math.pow(10, 15);
    double x5 = 3.0;
    double x6 = Math.pow(10, 12) * (-1);

    double y1 = Math.pow(10, 20);
    double y2 = 2.0;
    double y3 = Math.pow(10, 22) * (-1);
    double y4 = Math.pow(10, 13);
    double y5 = 2111.0;
    double y6 = Math.pow(10, 16);

    double erg = (x1 * y1) +(x3 * y3)+ (x2 * y2) + (x4 * y4)+(x5 * y5)+(x6 * y6);
    System.out.println(erg);
}
Run Code Online (Sandbox Code Playgroud)

非常感谢你的帮助.

rge*_*man 5

double您使用的值只有大约17-18位精度(53位).因此,当您添加小值和大值时,大值不会受到影响.然后减去大值,离开0.

在数学上,您正在计算表达式:

10 20 x 10 20 + 10 18 x(-10 22)+ 1,223 x 2 + 10 15 x 10 13 + 3 x 2,111 +( - 10 22)*10 16

简化:

10 40 - 10 40 + 2,446 + 10 28 + 6,333 - 10 28

数学上,10 40和-10 40取消,10 28和-10 28也取消,留下8,779.

由于doubles的精度有限,"小"值被消灭了.以下是Java中求和的每一步所发生的事情:

  1. 10 40 =>1.0E40
  2. - 10 40 =>0.0
  3. + 2,446 => 2446.0
  4. + 10 28 => 由于精度问题,1.0E28 这些2446被摧毁了.
  5. + 6,333 => 1.0E286333被因精度问题一扫而光.
  6. -10 28 =>0.0

要获得正确的值8779.0,首先进行取消,而不是在总和当前太大而无法满足精度时添加"小"值.

double erg = (x1 * y1) +(x3 * y3)+ (x4 * y4) + (x6 * y6) + (x2 * y2) +(x5 * y5);
Run Code Online (Sandbox Code Playgroud)