JAVA 的 Double.MIN_VALUE、IEEE 754 和 Google 的计算器?

JAVA's Double.MIN_VALUE, IEEE 754 and Google's calculator?

google的计算器可以计算出的最小非零数似乎是2^-1023。 IE。 2^-1024 等于 0。

在JAVA中Double.MIN_VALUE是2^-1074.

在此处和整个 Internet 上阅读有关 JAVA 的 Double.MIN_VALUE 时,有很多人提到 IEEE 754,但其中 none 实际上说 2^-1074 是最小的IEEE 754 中定义的非零数。

所以我的问题是:

  1. JAVA 的 Double.MIN_VALUE 与 IEEE 754 的定义有何关系 最小的非零数?有这样的事情吗?
  2. 为什么Google的计算器不能计算小于 2^-1023 显然有这样的数字? (我知道人们不 每天都使用它们,但编程语言仍然允许使用它们)
  3. 在 JAVA 中,如果 Double.MIN_VALUE == 4.9E-324 那么为什么 (Double.MIN_VALUE + Double.MIN_VALUE) == 1.0E-323 而不是 9.8E- 324,考虑到 (4.9E-5 + 4.9E-5) == 9.8E-5?
  4. 我应该向 Double.MIN_VALUE 添加多少才能使其等于零?

这是我针对这些问题制作的程序:

public class Lecture {
    public static void main(String[] args) {

        double min = Double.MIN_VALUE;
        double max = Double.MAX_VALUE;
        double minPlusOne = min + 0.0001;
        System.out.println("Min + 1: " + minPlusOne);
        System.out.println("Double.MIN_VALUE: " + min);
        System.out.println("Double.MIN_VALUE: " + max);
        double myMin = Math.pow(2, -1074);
        System.out.println("2^-1074: " + myMin);
        System.out.println("Double.MIN_VALUE == 2^-1074: "  + (min == myMin));
        System.out.println();

        System.out.println("Changed Min:" + (min + min));

        double a = 4.9E-5;
        double b = a + a;
        System.out.println(b);

    }
}

编辑:按照要求删除后续问题。

  1. 而不是"reading here and across the Internet",看看Javadoc就够了:

    A constant holding the smallest positive nonzero value of type double... and also equal to Double.longBitsToDouble(0x1L).

    即它的最后一位是1,其余都是0.

  2. 2^-1023 实际上不是那里的最小值,你可以得到 Double.MIN_VALUE 作为 (2^-1023)/2^51。不知道为什么 Google 的开发人员将 2^-1024 return 设为 0,你必须问他们。

  3. Double.MIN_VALUE 如文档所述,为 2^-1074。不是等于到4.9*10^-324,只是按照the specification of Double#toString打印成这样的。 Double.MIN_VALUE2*Double.MIN_VALUE 的四舍五入恰好朝着不同的方向进行。

  4. -Double.MIN_VALUE,就像任何其他 Double d 你会添加 -d.

How does JAVA's Double.MIN_VALUE relate to IEEE 754's definition of the smallest non-zero number? Is there such a thing at all?

你应该仔细阅读一本关于 FP 数字的好教程,例如 what every programmer should know about floating point arithmetic。 "Normal" 数字最小值为 2^-1023。但是 IEEE-754 也有 "subnormal"(或非正规)数字,其最小值为 2^-1074。这些数字可以更小,但精度损失很大。

Why does Google's calculator cannot calculate smaller numbers than 2^-1023 when apparently there are such numbers? (I know people don't use them every day but still, programming languages allow it).

并非所有硬件都支持非正规数,当支持时使用这些数字会带来 时间成本(例如,在奔腾运算符上,正常数的延迟约为 5 ,但如果结果或一个操作数是次正规的,则可以 >100)。这可能是 google 不支持次正规的原因(但这只是一个假设)。 FP 库和硬件可以将次正规数视为零。

In JAVA, if Double.MIN_VALUE == 4.9E-324 then why (Double.MIN_VALUE + Double.MIN_VALUE) == 1.0E-323 and not 9.8E-324, considering that (4.9E-5 + 4.9E-5) == 9.8E-5?

打印的值四舍五入并以二进制显示。 2^-1023 的整数部分的精确值比 4.9 的小数位数多得多。它的两倍是一样的。这是显示的问题。

How much should I add to Double.MIN_VALUE in order to make it equal zero?

自己减去就好了

您可以在任何搜索引擎中输入这些搜索词,而不是 "reading and across the internet":

IEEE 754 1074

您可能已经在维基百科上找到了以下对其进行了很好解释的文章:

https://en.wikipedia.org/wiki/IEEE_754-1985#Double_precision:

Double precision Double-precision numbers occupy 64 bits. In double precision:

  • The positive and negative numbers closest to zero (represented by the denormalized value with all 0s in the Exp field and the binary value 1 in the Fraction field) are

    ±2^−1074 ≈ ±4.94066×10^−324

  • The positive and negative normalized numbers closest to zero (represented with the> binary value 1 in the Exp field and 0 in the fraction field) are

    ±2^−1022 ≈ ±2.22507×10^−308

  • The finite positive and finite negative> numbers furthest from zero (represented by the value with 2046 in the Exp field and all 1s in the fraction field) are

    ±(1−2^−53) × 2^1024 ≈ ±1.79769×10^308

https://en.wikipedia.org/wiki/IEEE_754#Basic_and_interchange_formats:

Note that in the table above, the minimum exponents listed are for normal numbers; the special subnormal number representation allows even smaller numbers to be represented (with some loss of precision). For example, the smallest positive number that can be represented in binary64 is 2^−1074 (because 1074 = 1022 + 53 − 1).