DBL_MAX添加是如何工作的

How does DBL_MAX addition work?

本文关键字:工作 何工作 MAX 添加 DBL      更新时间:2023-10-16

代码

#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("%dn",f(DBL_MAX,DBL_MAX,-DBL_MAX));     
    printf("%dn",ff(LLONG_MAX,LLONG_MAX,-LLONG_MAX));
    return 0;
}

输出

0
1

我不明白为什么两种功能的工作方式不同。这里发生了什么?

在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:许多平台在二进制补码中执行有符号整数计算。Twos补码的添加是关联的,所以只要优化器不将其更改为与Twos补号规则相矛盾的内容,比较就会产生true。

后者是完全可能的(例如,请参阅本讨论(,因此您不能依赖于有符号整数溢出来执行我上面解释的操作。然而,它似乎";很好"在这种情况下。


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

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

如果在表达式求值过程中,结果未在数学上定义或不在其类型的可表示值,行为是未定义的。

事实就是这样。inf和NaN内容是允许的,但在C++和C浮点数学中不需要。仅当std::numeric_limits::is_iec559<T>对于所讨论的浮点类型为true时才需要。(或者在C中,如果它定义了__STDC_IEC_559__ 。否则,附录F的内容就不需要应用了。(如果iec指标中的任何一个保证了我们的IEEE语义,那么行为就可以很好地定义为执行我上面描述的操作。