Java 为什么浮点无穷大与NaN不同,是相等的?

Java 为什么浮点无穷大与NaN不同,是相等的?,java,floating-point,comparison,nan,infinity,Java,Floating Point,Comparison,Nan,Infinity,为什么无限比较不遵循应用于NaN的逻辑?此代码打印三次false: double a = Double.NaN; double b = Double.NaN; System.out.println(a == b); // false System.out.println(a < b); // false System.out.println(a > b); // false 这似乎很危险。假设溢出会产生无穷大的值,我想,在完美的算术中,两个最终成为无穷大的变量很可能实际上并不相

为什么无限比较不遵循应用于NaN的逻辑?此代码打印三次
false

double a = Double.NaN;
double b = Double.NaN;
System.out.println(a == b); // false
System.out.println(a < b); //  false
System.out.println(a > b); //  false

这似乎很危险。假设溢出会产生无穷大的值,我想,在完美的算术中,两个最终成为无穷大的变量很可能实际上并不相等。

这是因为NaN不是一个数字,因此不等于包括NaN在内的任何数字。

你的推理是,
Double。正无穷大
不应该等于它本身,因为它是“可能的”由于失去准确性而获得

这条推理路线适用于所有浮点运算。任何有限值都可以通过不准确的操作获得。这并没有促使IEEE 754标准化委员会将
=
定义为对于有限值总是计算为false,那么为什么无穷大应该不同呢

根据定义,
=
对于理解它的功能的人很有用(也就是说,测试已经获得的浮点值,当然不是应该通过实际计算获得的值)。对于任何理解这一点的人来说,你需要理解它,即使在不涉及无穷大的计算中使用浮点,让
Double.POSITIVE_infinity==Double.POSITIVE_infinity
求值为true也很方便,如果仅用于测试浮点计算的浮点结果是否为Double.POSITIVE_∞

这就留下了一个问题,为什么NaN可以有特殊的行为,而无穷大应该遵循与有限值相同的一般原则。NaN与无穷大不同:IEEE 754标准的基本原理是,值与实际值完全相同,但运算结果可以近似于实际结果,在这种情况下,根据舍入模式获得结果浮点值

暂时忘记一下,
1.0/0.0
被定义为+inf,这在本次讨论中是一个麻烦。考虑一下
1.0e100/1.0e-300
Double.MAX\u值+Double.MAX\u值等操作的结果。对于这些运算,+inf是与实际结果最接近的近似值,就像对于产生有限结果的运算一样。相反,NaN是当操作没有意义时得到的结果。让NaN有特殊的行为是有道理的,但inf只是太大而无法表示的所有值的近似值


实际上,
1.0/0.0
也会产生+inf,但是应该被视为例外。将该操作的结果定义为NaN同样连贯,但将其定义为+inf在某些算法的实现中更方便。第10页中提供了一个示例。比大多数人所希望的更多的细节都在报告中。我还认为,IEEE 754中存在一个与NaN标志分开的“零除”标志,即用户可能希望特别对待零除,尽管它没有被定义为产生NaN。

,因为这是标准。无穷大表示大于或小于Double.MAX\u VALUE//Double.MAX\u VALUE的数字

NaN代表的是一次毫无意义的行动的结果。也就是说,这次行动不可能有结果

我猜逻辑是,一旦一个数字足够大(无穷大),由于浮点数的限制,向它添加数字不会改变结果,所以它“像”无穷大


所以,如果你想和真正的大数字进行比较,在某个时候,你可能会说这两个大数字在所有意图和目的上都足够接近。但是如果你想比较两个都不是数字的东西,你不能比较它们,所以这是错误的。至少你不能将它们作为一个基本元素进行比较。

另一个证明“无限”值相等的观点是完全避免概念。基本上,如果你不能推测“一个值与另一个值相比有多大的无限性,假设两者都是无限的”,那么假设
Inf=Inf
就更简单了

编辑:为了澄清我关于基数的评论,我将给出两个关于无穷量比较(或相等)的例子

考虑一组正整数
S1={1,2,3,…}
,它是无限的。还考虑一组偶数整数<代码> S2= {2,4,6,…} /代码>,它们也是无限的。虽然S1中的元素数量明显是S2中的两倍,但它们的元素数量“相等”,因为您可以轻松地在集合之间使用一对一函数,即
1->2
2->4
。。。因此,它们具有相同的基数

考虑实数集
R
,以及整数集
I
。同样,两者都是无限集。但是,对于每个整数
i
,在
(i,i+1)
之间有无限多个实数。因此,没有一对一函数可以映射这两个集合的元素,因此它们的基数是不同的


底线:无穷量的相等是复杂的,在命令式语言中更容易避免:)

为什么无穷量相等?因为它有效

浮点运算的目的是产生(相对)快速的计算,从而保留错误。这个想法是,在一个漫长的计算过程中,你不需要检查溢出或其他废话;你要等到它完成。这就是为什么NaN会以他们的方式传播:一旦你得到了一个NaN,你几乎没有什么事情可以让它消失。计算完成后,您可以查找NaN以检查是否出现问题

无穷大也是一样:如果有
double a = Double.POSITIVE_INFINITY;
double b = Double.POSITIVE_INFINITY;
System.out.println(a == b); // true
System.out.println(a < b); //  false
System.out.println(a > b); //  false
SaturatedColor a = SaturatedColor.WHITE;
SaturatedColor b = SaturatedColor.WHITE;
SaturatedColor a = 127;
SaturatedColor b = 127;
System.out.println(127 == 127);
System.out.println(127 < 127);
System.out.println(127 > 127);