在C中评估以下表达式时,输出为零而不是无穷大。但是根据C运算符优先级规则,输出应该是无穷大。
double a=1/(1.0/0.0);
printf("a : %.18le\n", a);
请解释一下gcc编译器如何评估它?
答案 0 :(得分:6)
C标准没有规定双打如何处理NaN和Inf数,但是对于gcc,行为是由IEEE 754在严格模式下决定的:https://en.wikipedia.org/wiki/IEEE_754
来自那篇文章:
该标准定义了五个例外,每个例外都返回一个默认值 值并且具有相应的状态标志(除非在某些情况下) 发生异常时会引发下溢情况。没有其他 异常处理是必需的,但是附加的非默认值 推荐替代品(见下文)。
可能的五个例外是:
无效操作:数学上未定义,例如负数的平方根。默认返回qNaN。
除以零:对有限操作数的操作给出精确的无限结果,例如1/0或log(0)。默认返回±无穷大。
- 溢出:结果太大而无法正确表示(即,其无限指数范围的指数将大于 EMAX)。默认情况下,为圆到最近模式返回±无穷大。
- 下溢:结果非常小(超出正常范围)并且不准确。默认情况下返回一个次正规或零。
- 不精确:确切(即未接地)的结果无法准确表示。默认情况下返回正确舍入的结果。
但是在某些平台上,ieee 754兼容浮点单元不可用,您应该强制执行软件浮点库,或者参考平台手册了解会发生什么。例如,arm的fpu具有“RunFast”模式,禁用严格的合规性。
答案 1 :(得分:3)
让我们分解表达:
double a = 1 / (1.0 / 0.0);
首先评估表达式1.0 / 0.0
,结果为+infinity
。
然后评估下面的表达式:1.0 / +infinity
,这会得到0.0
,这是你得到的输出。
评估前int
1
被提升为double
。
所有其他答案也适用。
答案 2 :(得分:1)
IEEE-754定义的涉及无穷大的操作遵循相同的规则,基本上是非常大的有限数。将n除以n得到的数字随着n变大而接近于零,因此舍入限制为零。
答案 3 :(得分:1)
除了无穷大之外,用无穷大划分某些东西会导致零。 GCC正在产生正确的结果。