1 /(1.0 / 0.0)在C中评估为零

时间:2018-05-04 13:47:07

标签: c operator-precedence

在C中评估以下表达式时,输出为零而不是无穷大。但是根据C运算符优先级规则,输出应该是无穷大。

double a=1/(1.0/0.0);
printf("a : %.18le\n", a);

请解释一下gcc编译器如何评估它?

4 个答案:

答案 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”模式,禁用严格的合规性。

更多信息:Do any real-world CPUs not use IEEE 754?

答案 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正在产生正确的结果。