我认为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是不同的,但是从零以外的任何内容中减去这些都不会更改原始数字。

最佳答案

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

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

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

07-24 09:45
查看更多