1

我认为 MIN_NORMAL 是一个可以添加到“正常”双精度的值,并且数字会改变。例如,将 Double.MIN_NORMAL 添加到 0.1d,你会得到一个不同于 0.1d 的值,但是我的理解是错误的:

public static void test(double val) {
    if (val == (val - Double.MIN_NORMAL*1e50d))
        System.out.printf("val == (val - Double.MIN_NORMAL*1e50d) for val=%.20f\n", val);
    else
        System.out.printf("val != (val - Double.MIN_NORMAL*1e50d) for val=%.20f\n", val);
}

产生:

test(0.0d);
> val != (val - Double.MIN_NORMAL*1e50d) for val=0.00000000000000000000

test(1.0d);
> val == (val - Double.MIN_NORMAL*1e50d) for val=1.00000000000000000000

test(0.1d);
> val == (val - Double.MIN_NORMAL*1e50d) for val=0.10000000000000000000

有人请在这里解释什么违背了我的逻辑,即使我将 MIN_NORMAL 乘以 1e50d,我仍然得到相同的数字。

我检查了二进制表示,并且 1 * Double.MIN_NORMAL 与 2 * Double.MIN_NORMAL 不同,但是从除零之外的任何内容中减去它们不会改变原始数字。

4

2 回答 2

2

双精度有限。MIN_NORMAL 是 2e-1022。除非您将其添加到的数字也在 2e-1000 的范围内,否则它将被删除。

于 2014-06-05T01:30:06.593 回答
2

MIN_NORMAL正如Javadoc所说,只是最小的标准化double值。但这并不意味着它类似于s:1对于int浮点值,根本没有标准的“eps”可以添加以更改为下一个可表示的值——“eps”始终取决于给定的浮点值。这就是为什么它们最终被称为浮点数:)

但是,Java 1.6+ 提供了Math.nextAfter()对于任何给定double的返回下一个或上一个可表示的double.

在较旧的 Java 版本上,您总是可以乱用Double.doubleToLongBits(),递增或递减其结果,然后转换回Double.longBitsToDouble(); 这将为您提供下一个或上一个可表示的double值 -在大多数情况下:有一些特殊情况(NaN,无限值),因此不建议浮点新手使用 :)

于 2015-03-01T19:48:21.837 回答