- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
代码
#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
我无法理解为什么这两个函数的工作方式不同。这里发生了什么?
最佳答案
在 C++ 和 C 标准看来,整数版本和浮点版本可能会调用未定义行为,因为计算结果 x + y
在执行算术的类型中不可表示。†因此这两个函数都可能产生甚至做任何事情。
但是,许多现实世界的平台为浮点运算提供额外的保证,并以某种方式实现整数,让我们解释您得到的结果。
考虑f
,我们注意到许多流行的平台实现了 IEEE 754 中描述的 float 学。遵循该标准的规则,我们得到 LHS:
DBL_MAX + DBL_MAX = INF
和
INF - DBL_MAX = INF.
RHS yield
DBL_MAX - DBL_MAX = 0
和
DBL_MAX + 0 = DBL_MAX
因此 LHS != RHS。
继续 ff
:许多平台以二进制补码执行有符号整数计算。二进制补码的加法是关联的,因此只要优化器不将其更改为与二进制补码规则相矛盾的内容,比较结果就会为真。
后者是完全可能的(例如参见 this discussion ),因此您不能依赖有符号整数溢出来执行我上面解释的操作。然而,在这种情况下,它似乎“很好”。
†请注意,这绝不适用于无符号整数运算。在 C++ 中,无符号整数实现算术模 2^NumBits
其中 NumBits
是该类型的位数。在这个算法中,每个整数都可以通过在 [0, 2^NumBits - 1]
中选择其等价类的代表来表示。 .所以这个算法永远不会溢出。
对于那些怀疑浮点情况是潜在 UB 的人:N4140 5/4 [expr] 说
If during the evaluation of an expression, the result is not mathematically defined or not in the range ofrepresentable values for its type, the behavior is undefined.
是这样的。 inf 和 NaN 是允许的,但在 C++ 和 C float 学中不是必需的。仅当 std::numeric_limits::is_iec559<T>
时才需要对于所讨论的浮点类型是正确的。 (或者在 C 中,如果它定义了 __STDC_IEC_559__
。否则,不需要应用附件 F 的内容。)如果 iec 指示符中的任何一个保证我们的 IEEE 语义,则行为被明确定义为执行我上面描述的操作。
关于c++ - DBL_MAX 加法是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38826007/
我正在尝试为所有可表示的有限值生成具有大致相等概率的随机 double 。我相信这类似于随机签名的 exponential_distribution,uniform_distribution 将不起作
在 Visual C++ 2010 中,我试过这个 double d= DBL_MAX; double dblmaxintpart; modf(DBL_MAX, &dblmaxintpart); 在我
如果之前有人问过这个问题,我深表歉意,但我通读了许多 DBL_MAX 线程,但没有看到这个确切的问题。 在我的 float.h header 中,变量定义为 #define DBL_MAX
我刚刚读到有关 IEEE 754 的信息标准以了解如何single-precision和 double-precision实现了 float 。 所以我写了这个来检查我的理解: #include #
代码 #include #include #include int f( double x, double y, double z){ return (x+y)+z == x+(y+z); }
我在某处看到这段代码 printf("DBL_MAX : %g\n", (double) DBL_MAX); Actor 是必要的吗?我在标准中找不到任何指定 DBL_MAX 必须实际具有
这一行: NSLog(@"DBL_MAX: %f", DBL_MAX); 打印这个非常大的值:17976931348623157081452742373170435679807056752584499
我代表一个“物理上不可能”的值,在计算机上可能代表的最负值。 #include double physically_impossible = -DBL_MAX; 这个测试效果很好 if( physi
我在我的 iPhone 上运行这段代码: double d = DBL_MAX; NSString *s = [NSString stringWithFormat:@"%.0f", d]; doubl
我想要极端的值(value)。 #include using namespace std; #include #include #include #define THRESHOLD 2*DBL
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve th
我正在编写一个 ptree,在某些时候我需要将 DBL_MAX 放入(作为默认值)。打开生成的 xml 文件时,我看到了正确的数字。 但是当我使用 ptree.get 获取数字时抛出异常:conver
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 8 年前。 Improve t
我使用的是 Embarcadero RAD Studio 的评估版。我为静态库中的代码和主应用程序中的代码获得了不同的 DBL_MAX 值。 代码是 双 x = DBL_MAX; 在静态库的代码中,x
我的一个函数返回一个 double,我想用一个无效值来指示错误条件,例如 DBL_MIN、DBL_MAX 或 -DBL_MAX。 #include #include #include doubl
我正在登录(写入文件)backgroundTimeRemaining每次我的应用程序从挂起模式唤醒时的值,就在我使用过期处理程序开始 UIApplication 的后台任务之前,就像这样(在我发出网络
我正在查看由以下代码片段生成的日志消息。 Flog 是用于调用内部日志记录类的#define。 代码来 self 项目中包含的 Pod 中的源文件。我不知道这是否重要。 我对这条消息感到困惑,因为在执
源代码(我不确定这是哪个版本,它只是网站的摘录)。在 for 循环的最开始,注释说“我们已经获得了足够的数字,我们将忽略其余的”。 为什么这是真的?为什么这“并不一定意味着结果会溢出。”? /* Co
在我的代码中,我使用了在 math.h 中定义的 DBL_MAX。在 VS2010 中它工作正常,但在 VS2008 中出现错误: error: C2065: 'DBL_MAX' : undeclar
在进行转换测试时,我在 C++ 中遇到了一些奇怪的行为。 上下文 网上的C++引用表明std::numeric_limits::max()的返回值(在 limit.h 中定义)应该是 DBL_MAX
我是一名优秀的程序员,十分优秀!