Java 为什么在定义浮点数的“齐平到零”和“齐平到无穷大”的值时会有这样不同的不对称规则?

Java 为什么在定义浮点数的“齐平到零”和“齐平到无穷大”的值时会有这样不同的不对称规则?,java,floating-point,Java,Floating Point,为什么Double.MIN\u值==Math.ulp(Double.MIN\u值)//4.9E-324 而Double.MAX_值!=Math.ulp(双精度最大值) 我认为在小于Double.MIN\u VALUE-Math.ulp(Double.MIN\u VALUE)的浮点值时,会发生零刷新。但是这不是真的,除了Double.MIN_值和Math.ulp(Double.MIN_值)是相等的之外。实际上,齐平到零发生在Math.ulp(Double.MIN_值)/2正下方(小于该值) 但是,

为什么
Double.MIN\u值==Math.ulp(Double.MIN\u值)//4.9E-324

Double.MAX_值!=Math.ulp(双精度最大值)

我认为在小于
Double.MIN\u VALUE-Math.ulp(Double.MIN\u VALUE)
的浮点值时,会发生零刷新。但是这不是真的,除了Double.MIN_值和Math.ulp(Double.MIN_值)是相等的之外。实际上,齐平到零发生在
Math.ulp(Double.MIN_值)/2
正下方(小于该值)

但是,在
Double.MAX\u值+Math.ulp(Double.MAX\u值)
处会出现无限刷新。值得注意的是,
Double.MAX\u值+Integer.MAX\u值==Double.MAX\u值
(因为Integer.MAX\u值 为什么刷新到零的逻辑与刷新到无穷大的逻辑不同?我的意思是why flush to zero不是与Double.MIN\u VALUE-Math.ulp(Double.MIN\u VALUE)/2//相同的Double.MIN\u VALUE-对称地flush to无穷大,发生在Double.MAX\u VALUE+Math.ulp(Double.MAX\u VALUE)/2和
-Double.MAX\u VALUE-Math.ulp(Double.MAX\u VALUE)/2


我的研究:C++是唯一的。 您观察到的效果称为逐渐下溢。它被设计成浮点运算,以避免数字中的位可能是较大数字的一部分,但不能独立存在

考虑以下代码:

if (a == b)
    printf("The divisor is zero.\n");
else
    printf("The quotient is %g.\n", c / (a-b));
考虑一下如果
a
为1.25×2会发生什么情况−1022和
b
为1×2−1022.
a
b
是不同的,因此
a==b
为false。如果你对它们进行细分得到零,因为.25×2−1022小于截止值,则
c/(a-b)
将导致异常并产生无穷大,即使
c
是一个小值且数学结果是可表示的。我们希望这段代码能够正常工作,用户在这段代码中进行了测试以避免出现错误。逐渐下溢意味着,如果一个值中有一个位(或多个位),我们可以用该位(或多个位)进行算术运算。减去数字中的其他位将保留该位,而不是突然跳到零

渐进下溢避免了奇怪的情况,即减去两个数字,结果会以很大的方式跳跃(相对于所涉及的震级)

if (a == b)
    printf("The divisor is zero.\n");
else
    printf("The quotient is %g.\n", c / (a-b));