我认为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
值。但这并不意味着它类似于1
的int
:对于浮点数,根本就没有标准的“ eps”可以添加到下一个可表示的值,即“ eps”。始终取决于给定浮点值的指数。这就是为什么它们最终被称为浮点数的原因:)
但是,Java 1.6+提供了Math.nextAfter()
,它为任何给定的double
返回下一个或上一个可表示的double
。
在较旧的Java版本上,您总是可以弄乱Double.doubleToLongBits()
,递增或递减其结果,然后按Double.longBitsToDouble()
转换回去。这将为您提供下一个或上一个可表示的double
值-在大多数情况下:有一些特殊情况(NaN,无穷大值),因此不建议对浮点型新手使用:)