请您在考虑我之前要求同样的N%问题之前先阅读它,并请注意它。
我正在开发一个项目,我有更多的函数返回double,它们中的一些可能是相同的,这在我的项目中是一件好事,如果是真的那么我需要一个{{ 1}}比较,看看是否相等。
我知道进行平等比较double
并不是一件明智的事情,我们也不需要说出原因,但我们可以查看if( x == y )
或<
这个问题的一部分。
语言(标准)是否保证这一点,比较>
和<
是100%?
如果是,那么可以使用以下程序:
>
#include <stdio.h>
int main(void){
double x = 3.14;
double y = 3.14;
if( x < y || x > y){
/* Are not Equal */
}else{
/* Are Equal, foo() will be called here\n" */
foo(x, y);
}
}
会被执行吗?因为此处foo(x, y);
和X
应该相等。
修改 这个问题并没有找到比较两个双重的方法,只是我应该使用的事实,或者我不应该使用&lt; &gt; 而不是 ==
答案 0 :(得分:3)
我知道进行平等比较
if( x == y )
并不是一件明智的事情
这根本不是真的。根据具体问题,做或做错事可能是正确的。
if (x < y || x > y)
这保证了与 1 完全相同的效果
if (x != y)
与
相反的效果if (x == y)
当一个人错了,另一个也错了。当一个是对的,另一个是对的。用<
和>
符号而不是==
或!=
写出相等条件并不会突然变得更聪明。
[1]除非其中一个操作数是NaN。
答案 1 :(得分:1)
如果你想要小数等式,你要么必须使用epsilon比较(即检查数字是否在特定阈值内彼此足够接近),或者非常小心地使用某些定点算法以避免舍入错误
是的,同样的问题被提出的次数超过了必要的次数:
您需要更多地了解比较的工作原理,特别是为什么浮点相等不起作用。这似乎与equals运算符本身无关,正如您所想的那样(对于算术类型[当不涉及NaN等特殊值时],!(x > y || y > x)
将始终与x == y
相同。事实上,大多数编译器会优化x < y || x > y
到x != y
),而是因为舍入误差首先是浮点运算的基本部分。 x == y
确实适用于浮点类型,您可以自由地执行它。在进行任何算术运算之后它会成为一个问题,然后想要比较它们,因为舍入错误会发生什么是不可预测的。
基本上,是的。比较平等你想要的除非你实际上做双打的任何事情。如果您只是将它们用作索引或类似的东西,那么只要您知道要为它们分配相同的值,就不会有问题。使用布尔标识不会使您免于浮点数的基本功能。
答案 2 :(得分:1)
首先,你的条件有点偏。检查你想要的不平等
( x < y || y < x)
不是
(x < y || y > x )
只检查两次相同的东西,意思是x&lt; y回来是假的。
忽略这个小问题:
是&gt;和&lt;应该是100%,因为它几乎总是与==相同。唯一的区别是与Nan的不同行为。但它并没有解决你的问题。
这是一个非常人为的例子。
#include <stdio.h>
void foo(double x, double y){
printf( "OK a:%f, b:%f\n",x,y);
}
void bar(double x, double y){
printf( "BAD a:%f, b:%f\n",x,y);
}
int main(void){
double x = 3.14;
double y = 3.14;
if( x < y || y < x){
/* Are not Equal */
bar(x, y);
}else{
/* Are Equal, foo() will be called here\n" */
foo(x, y);
}
for( int i = 0; i < 1000; i++) {
y = y + 0.1;
}
x = x + 100;
if( x < y || y < x){
bar(x, y);
}else{
/* Are Equal, foo() will be called here\n" */
foo(x, y);
}
}
这是你的输出(暗示它的坏)
$ ./a.exe
OK a:3.140000, b:3.140000
BAD a:103.140000, b:103.140000
我知道双重平等的最佳实践是检查某些epsilon中的接近程度,
eps = 0.00000000001
if( abs( x - y ) < eps ) {
printf("EQUAL!");
}
答案 3 :(得分:1)
其中一些是相同的......如果是真的那么我需要进行双重比较以确定是否相等。
OP正在质疑测试FP平等的两种不同方法,并想知道它们是否在功能上相似。
除了可能没有被C定义的NaN(但由IEEE 754明确定义),两个比较相似但失败锥形等价测试
考虑这个double
代码:
if (a==b) {
double ai = 1.0/a;
double bi = 1.0/b;
printf("%d\n", ai == bi);
} else {
printf("%d\n", 1);
}
结果总是 "1"
吗?以下是一个例外(鼠标结束)
考虑
a=0.0; b=-0.0
。两者都是相同的,但它们的反转通常是不一样的。一个是正无穷大,另一个是负无穷大。
问题归结为你需要如何? NaN重要吗?使用memcmp(&a, &b, sizeof a)
肯定是一个强大的测试,并且对于选择系统来说可能太强大了FP编号可以具有相同的非零值,但编码不同。如果这些差异很重要,或者只是上面的例外情况,则由OP决定。
如果测试2个不同的代码/函数是否产生相同的binary64结果,请考虑评估其Unit-in-the-Last-Place差异。类似于以下内容:将unsigned long long ULP_diff()
与0,1或2进行比较,具体取决于您的容错能力。
// not highly portable
#include <assert.h>
unsigned long long ULP(double x) {
union {
double d;
unsigned long long ull;
} u;
assert(sizeof(double) == sizeof(unsigned long long));
u.d = x;
if (u.ull & 0x8000000000000000) {
u.ull ^= 0x8000000000000000;
return 0x8000000000000000 - u.ull;
}
return u.ull + 0x8000000000000000;
}
unsigned long long ULP_diff(double x, double y) {
unsigned long ullx = ULP(x);
unsigned long ully = ULP(y);
if (x > y) return ullx - ully;
return ully - ullx;
}
答案 4 :(得分:-2)
#include <stdio.h>
int main(void){
double x = 3.14;
double y = 3.14;
if( x < y || x > y){
/* Are not Equal */
}else{
/* Are Equal, foo() will be called here\n" */
printf("yes");
}
}
打印是