DBL_MAX添加如何工作?

时间:2016-08-08 09:47:42

标签: c++ c double

代码

#include<stdio.h>
#include<limits.h>
#include<float.h>

int f( double x, double y, double z){
  return  (x+y)+z == x+(y+z);
}

int ff( long long x, long long y, long long z){
  return  (x+y)+z == x+(y+z);
}

int main()
{
    printf("%d\n",f(DBL_MAX,DBL_MAX,-DBL_MAX));     
    printf("%d\n",ff(LLONG_MAX,LLONG_MAX,-LLONG_MAX));
    return 0;
}

输出

0
1

我无法理解为什么两个函数的工作方式不同。这里发生了什么?

1 个答案:

答案 0 :(得分:4)

在C ++和C标准的眼中,整数版本肯定和浮点版本可能会调用未定义的行为,因为计算结果x + y在执行算术的类型中是不可表示的。 所以这两个函数都可能产生甚至做任何事情。

然而,许多真实世界的平台为浮点运算提供了额外的保证,并以某种方式实现了整数,让我们可以解释你得到的结果。

考虑到f,我们注意到许多流行的平台实现了IEEE 754中描述的浮点数学。遵循该标准的规则,我们得到了LHS:

DBL_MAX + DBL_MAX = INF

INF - DBL_MAX = INF.

RHS收益率

DBL_MAX - DBL_MAX = 0

DBL_MAX + 0 = DBL_MAX

因此LHS!= RHS。

继续ff:许多平台以二进制补码执行有符号整数计算。二进制补码的加法是偶像的,所以只要优化器不会将它改为与二进制补码规则相矛盾的东西,比较就会产生真实。

后者是完全可能的(例如参见this discussion),所以你不能依赖有符号整数溢出来做我上面解释的。然而,似乎它很好&#34;在这种情况下。

请注意,这绝不适用于无符号整数运算。在C ++中,无符号整数实现算术模2^NumBits,其中NumBits是该类型的位数。在此算法中,可以通过在[0, 2^NumBits - 1]中选择其等价类的代表来表示每个整数。所以这个算术永远不会溢出。

对于那些怀疑浮点情况是潜在的UB的人:N4140 5/4 [expr]说

  

如果在评估表达式期间,结果未在数学上定义或不在范围内   其类型的可表示值,行为未定义。

情况就是这样。允许使用inf和NaN,但在C ++和C浮点数学中不需要。仅当std::numeric_limits::is_iec559<T>对于所讨论的浮点类型为真时才需要它。 (或者在C中,如果它定义__STDC_IEC_559__。否则,附件F的东西不需要应用。)如果任何一个iec指示符保证我们的IEEE语义,那么行为很好地定义为执行我上面描述的。