在C中,在使用IEEE-754浮点数的实现中,当我比较两个NaN的浮点数时,它返回0或" false"。但是为什么两个浮点数都被认为是相等的呢?
本程序打印等于:..." (至少在使用gcc的Linux AMD64下)并且在我看来它应该打印不同的:......"。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
volatile double a = 1e200; //use volatile to suppress compiler warnings
volatile double b = 3e200;
volatile double c = 1e200;
double resA = a * c; //resA and resB should by inf
double resB = b * c;
if (resA == resB)
{
printf("equal: %e * %e = %e = %e = %e * %e\n",a,c,resA,resB,b,c);
}
else
{
printf("different: %e * %e = %e != %e = %e * %e\n", a, c, resA, resB, b, c);
}
return EXIT_SUCCESS;
}
另一个例子,为什么我认为inf与inf不同,是:自然数和有理数的数字,都是无限的但不一样。
那么为什么inf == inf?
答案 0 :(得分:5)
无限比较相等,因为这就是标准所说的。来自 5.11部分比较谓词的详细信息:
相同符号的无限操作数应比较相等。
答案 1 :(得分:2)
inf==inf
出于同样的原因,几乎所有浮点数都与自己相等:因为它们相等。它们包含相同的符号,指数和尾数。
你可能在考虑如何NaN != NaN
。但这对于一个更重要的不变量来说是一个相对不重要的结果:NaN != x
对于任何 x
。顾名思义,NaN
根本不是任何数字,因此无法比较等于任何数字,因为所讨论的比较是数字比较(因此为-0 == +0
) 。
将inf
与其他inf
进行比较不等于肯定会有一些意义,因为在数学语境中,他们几乎肯定是不平等的。但请记住,浮点平等与绝对数学平等不同; 0.1f * 10.0f != 1.0f
和1e100f + 1.0f == 1e100f
。正如浮点数逐渐下降到非正规数而不会损害尽可能好的平等,所以它们会溢出到无穷大而不会损害尽可能好的平等。
如果您需要inf != inf
,则可以模拟它:1e400 == 3e400
的计算结果为true,但1e400 - 3e400 == 0
的计算结果为false,因为+inf + -inf
的结果为{{1} }。 (可以说你可以说它应该评估为NaN
,但这对任何人都没有兴趣。)
答案 2 :(得分:1)
<强>背景强>
在C中,根据IEEE 754二进制浮点标准(因此,如果您使用float
或double
),您将得到一个可以与之完全比较的精确值另一个相同类型的变量。好吧,除非你的计算结果是一个超出可以表示的整数范围的值(即溢出),否则这是真的。
为什么Infinity == Infinity
resA
和resB
IEEE-754标准将无穷大和负无穷大的值分别大于或小于可根据标准(<= INFINITY == 0 11111111111 0000000000000000000000000000000000000000000000000000
和>= -INFINITY == 1 11111111111 0000000000000000000000000000000000000000000000000000
)表示的所有其他值, NaN 除外,它既不小于,等于或大于任何浮点值(甚至本身)。请注意,无穷大和它的负数在其符号,指数和尾数位中都有明确的定义。
因此,resA
和resB
是无穷大的,因为无穷大是明确定义和可重现的,resA==resB
。我很确定这是isinf()
的实施方式。
为什么NaN!= NaN
但是,没有明确定义NaN。 NaN值的符号位为0
,所有1
的指数位(就像无穷大而且为负),以及任何非零小数位(Source)。那么,如果他们的分数位是任意的,你怎么能告诉另一个NaN呢?好吧,标准没有假设,当这个结构的两个浮点值相互比较时,只返回false。
更多解释
因为无穷大是明确定义的值(来源,GNU C Manual):
无限性通过计算传播
2 +∞=∞
4÷∞= 0
arctan(∞)=π/ 2。
然而,NaN可能会也可能不会通过计算传播。当它发生时,它是一个QNan(Quieting NaN,最重要的分数位集),所有计算都将导致NaN。当它没有时,它是一个SNan(信令NaN,未设置的最重要的分数位),所有计算都将导致错误。
答案 3 :(得分:0)
有许多算术系统。其中一些,包括高中数学中通常涵盖的那些,例如实数,没有无穷大的数字。其他人只有一个无穷大,例如projectively extended real line。其他的,例如正在讨论的IEEE浮点运算,以及extended real line,都有正无穷大。
IEEE754算法在很多方面与实数算术不同,但对于许多目的来说是一个有用的近似。
对NaNs和无穷大的不同处理有逻辑。说正无穷大大于负无穷大和任何有限数是完全合理的。对-1的平方根说任何类似的东西都是不合理的。