java.lang.Double 的精度损失

Precision loss with java.lang.Double

假设我有 2 个 double 值。一个很大,一个很小。

double x = 99....9;  // I don't know the possible max and min values,
double y = 0,00..1;  // so just assume these values are near max and min.

如果我将这些值加在一起,我会失去精度吗?

换句话说,如果我给它分配一个 int 值,最大可能的 double 值会增加吗?如果我选择一个小的整数部分,最小可能 double 值会减少吗?

double z = x + y;    // Real result is something like 999999999999999.00000000000001

double 值并未均匀分布在所有数字上。 double 使用数字的浮点表示,这意味着您有固定数量的位用于指数和固定数量的位用于表示实际 "numbers"/尾数。

因此,在您的示例中,使用较大值和较小值会导致丢弃较小的值,因为它无法使用较大的指数表示。

不降低精度的解决方案是使用具有潜在增长精度的数字格式,如 BigDecimal - 它不限于固定位数。

如果您尝试为 double 分配太大或太小的值,编译器将给出错误:

试试这个

    double d1 =  1e-1000;
    double d2 =  1e+1000;

我使用的是十进制浮点运算,精度为三位十进制数字,并且(大致)具有与典型二进制浮点运算相同的功能。假设您有 123.0 和 4.56。这些数字由尾数 (0<=m<1) 和指数表示:0.123*10^3 和 0.456*10^1,我将其写为 <.123e3> 和 <.456e1>。除非指数相等,否则不可能立即将两个这样的数字相加,这就是加法根据以下公式进行的原因:

 <.123e3>   <.123e3>
 <.456e1>   <.004e3>
            --------
            <.127e3>

您看到根据公共指数对小数位进行必要的对齐会导致精度损失。在极端情况下,整个加数可能会变成虚无。 (考虑对一个无限级数求和,其中的项变得越来越小,但仍会对计算的总和做出很大贡献。)

不精确的其他来源是二进制和十进制小数之间的差异,其中一个基数中的精确分数无法使用另一个基数准确无误地表示。

所以,简而言之,不同数量级的数字之间的加减法必然会导致精度损失。