[英]Bug in my floating point code, or gcc?
The following code works as expected for me under 64-bits, but fails under 32-bit at -O2 and -O3, the expected output is 1.1, under the bugged systems it prints 1.0. 下面的代码在64位下按预期工作,但在32位at -O2和-O3下失败,预期输出为1.1,在它打印1.0的错误系统下。 I'm trying to establish if this is a bug in my code (making some bad assumptions about how floats work) or in GCC.
我试图确定这是否是我的代码中的错误(对浮点数如何工作做出一些错误的假设)或在GCC中。 If it's in my code, how on earth do I go about fixing it?
如果它在我的代码中,我该如何修复它?
#include <math.h>
#include <stdio.h>
int f(double x) {
return isinf(1.0 / x);
}
int m_isinf(double x) {
return x != 0 && x * 0.5 == x;
}
int g(double x) {
return m_isinf(1.0 / x);
}
double values[] = {
5.5e-309,
-1.0
};
int main() {
int i;
for (i = 0; values[i] != -1.0; i++) {
printf("%d\n", f(values[i]));
printf("%d\n", g(values[i]));
}
return 0;
}
Expression may be evaluated with more precision than the type. 可以比类型更精确地评估表达式。 In your 32 bit build, the compiler is probably using the 80 bits long double (which is no more used in 64 bits) to evaluate
x != 0 && x * 0.5 == x
. 在32位版本中,编译器可能使用80位长的双精度(在64位中不再使用)来计算
x != 0 && x * 0.5 == x
。
(GCC has know problems with this rules, evaluating with more precisions in context where it can't). (海湾合作委员会已经知道这个规则存在问题,在不能确定的情况下进行更精确的评估)。
6.3.1.8/2 in C99 (6.2.1.5 in C90 is equivalent): C99中的6.3.1.8/2(C90中的6.2.1.5是等效的):
The values of floating operands and of the results of floating expressions may be represented in greater precision and range than that required by the type;
浮动操作数的值和浮动表达式的结果可以以比该类型所需的精度和范围更高的精度和范围来表示; the types are not changed thereby
因此不改变类型
In a conforming implementation: 在符合要求的实施中:
int m_isinf(double x) {
double const half_x = x * 0.5;
return x != 0 && half_x == x;
}
should work. 应该管用。 But gcc bug ( http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 look at the number of duplicates) often prevent this to work.
但是gcc bug( http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323查看重复数量)经常阻止这种情况发生。 There are some work around in the bug report.
bug报告中有一些工作。
基本上,在浮点数和双精度数上使用相等比较是意外行为的可靠方法。
You can check the value directly, like so: 您可以直接检查值,如下所示:
#include <math.h>
int isinf(double d) {
union {
unsigned long long l;
double d;
} u;
u.d=d;
return (u.l==0x7FF0000000000000ll?1:u.l==0xFFF0000000000000ll?-1:0);
}
Courtesy of dietlibc 由dietlibc提供
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.