除了可能不同大小的寄存器之外,您还需要担心非规范化浮点(cq 刷新为零)(请参阅为什么将 0.1f 更改为 0 会使性能降低 10 倍?)
只是为了了解这可能导致的怪异,请尝试以下代码:
float a = 0.000000000000000000000000000000000000000047683384;
const float b = 0.000000000000000000000000000000000000000047683384;
float aa = a, bb = b;
#define SUPPORT_DENORMALIZATION ({volatile double t=DBL_MIN/2.0;t!=0.0;})
printf("support denormals: %d\n",SUPPORT_DENORMALIZATION);
printf("a = %.48f, aa = %.48f\na==aa %d, a==0.0f %d, aa==0.0f %d\n",a,aa,a==aa,a==0.0f,aa==0.0f);
printf("b = %.48f, bb = %.48f\nb==bb %d, b==0.0f %d, bb==0.0f %d\n",b,bb,b==bb,b==0.0f,bb==0.0f);
这给出了:(编译时没有清零)
support denormals: 1
a = 0.000000000000000000000000000000000000000047683384, aa = 0.000000000000000000000000000000000000000047683384
a==aa 1, a==0.0f 0, aa==0.0f 0
b = 0.000000000000000000000000000000000000000047683384, bb = 0.000000000000000000000000000000000000000047683384
b==bb 1, b==0.0f 0, bb==0.0f 0
或:(用 编译gcc -ffast-math
)
support denormals: 0
a = 0.000000000000000000000000000000000000000000000000, aa = 0.000000000000000000000000000000000000000000000000
a==aa 1, a==0.0f 1, aa==0.0f 1
b = 0.000000000000000000000000000000000000000047683384, bb = 0.000000000000000000000000000000000000000000000000
b==bb 1, b==0.0f 0, bb==0.0f 1
最后一行当然是奇怪的:b==bb && b!=0.0f && bb==0.0f
这是真的。
所以如果你还在考虑比较浮点值,至少要远离小值。
更新以抵消一些关于这是由于使用浮点数而不是双精度数的评论,它也适用于双精度数,但您需要将常量设置为以下某处DBL_MIN
,例如1e-309
.
更新 2与下面的一些评论相关的代码示例。这表明双精度数也存在问题,并且比较可能会变得不一致(启用刷新为零时)
double a;
const double b = 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001225;
const double c = 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002225;
printf("b==c %d\n",b==c);
a = b;
printf("assigned a=b: a==b %d\n",a==b);
a = c;
printf("assigned a=c: a==b %d\n",a==b);
输出:
b==c 0
assigned a=b: a==b 1
assigned a=c: a==b 1
问题显示在最后一行,您会天真地期望a==b
在分配a=c
with后会变为错误c!=b
。