DBL_MAX添加是如何工作的
How does DBL_MAX addition work?
代码
#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语义,那么行为就可以很好地定义为执行我上面描述的操作。
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 当 int 方法工作正常时,void 方法有何不同,或者为什么我不能调用 void 方法?
- sdl软件渲染器不工作,工作在硬件加速的一个