1)您正在尝试与浮点进行等于比较。一些浮点格式可以工作,但 IEEE 格式不能工作。你不能做等于比较。您需要将该浮点数转换为 int 然后进行 int 比较。使用整数(不限于 32 位或此处的任何内容)只有一种表示每个数字的方法,因此您可以进行等于比较。
2)记住浮点数学是以2为底的,而你要求做以10为底的东西。所以会有转换问题,截断。此外,我再次假设您使用的是 IEEE,这意味着您具有三种舍入模式(以 2 为底),因此您也必须处理它。你会想做某种 double_to_integer((double*1000.0)+0.5) 并比较它们。如果您发现不起作用的极端案例,我不会感到惊讶。
有关此问题的更多有趣信息。请注意,C 标准不支持以这种方式使用联合,但通常恰好可以工作......
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
double trunc(double d)
{
return (d>0) ? floor(d) : ceil(d) ;
}
int comparedigits(float a , float b)
{
if (trunc(1000.0 * a) == trunc(1000.0 * b))
{
return 1;
}
return 0;
}
union
{
unsigned int ul;
float f;
} fun;
union
{
unsigned int ul[2];
double d;
} dun;
int main ( void )
{
float g;
float h;
int t;
g = 2.346;
h = 2.34599;
t = comparedigits(g,h);
printf("%u\n",t);
printf("raw\n");
fun.f=g; printf("0x%08X\n",fun.ul);
fun.f=h; printf("0x%08X\n",fun.ul);
dun.d=g; printf("0x%08X_%08X\n",dun.ul[1],dun.ul[0]);
dun.d=h; printf("0x%08X_%08X\n",dun.ul[1],dun.ul[0]);
printf("trunc\n");
dun.d=trunc(1000.0 * g); printf("0x%08X_%08X\n",dun.ul[1],dun.ul[0]);
dun.d=trunc(1000.0 * h); printf("0x%08X_%08X\n",dun.ul[1],dun.ul[0]);
printf("trunc\n");
dun.d=trunc(1000.0F * g); printf("0x%08X_%08X\n",dun.ul[1],dun.ul[0]);
dun.d=trunc(1000.0F * h); printf("0x%08X_%08X\n",dun.ul[1],dun.ul[0]);
printf("floor\n");
dun.d=floor(1000.0 * g); printf("0x%08X_%08X\n",dun.ul[1],dun.ul[0]);
dun.d=floor(1000.0 * h); printf("0x%08X_%08X\n",dun.ul[1],dun.ul[0]);
printf("ceil\n");
dun.d=ceil(1000.0 * g); printf("0x%08X_%08X\n",dun.ul[1],dun.ul[0]);
dun.d=ceil(1000.0 * h); printf("0x%08X_%08X\n",dun.ul[1],dun.ul[0]);
printf("%u\n",(unsigned int)(g*1000.0));
printf("%u\n",(unsigned int)(h*1000.0));
if (trunc(1000.0F * g) == trunc(1000.0F * h))
{
printf("true\n");
}
else
{
printf("false\n");
}
return(0);
}
编译运行
gcc test.c -o test -lm
./test
1
raw
0x401624DD
0x401624B3
0x4002C49B_A0000000
0x4002C496_60000000
trunc
0x40A25200_00000000
0x40A25200_00000000
trunc
0x40A25400_00000000
0x40A25200_00000000
floor
0x40A25200_00000000
0x40A25200_00000000
ceil
0x40A25400_00000000
0x40A25400_00000000
2345
2345
false
所以在单数学而不是双数学中做 1000 * x 似乎可以解决问题
1000.0 * a 是混合模式。除非指定为单,否则 1000.0 是 C 标准的双精度。并且 a 是单数,因此 a 被转换为双数,数学以双数形式完成,然后将其馈送到双精度函数。1000.0F 是单数,a 是单数,所以乘以单数运算,然后转换为双数。所以也许真正的问题在于 g 和 h 的转换和舍入为双精度数。将不得不更多地挖掘尾数差异......
我觉得关键是这个,双倍单1000.0*x的结果
trunc
0x40A25200_00000000
0x40A25200_00000000
如果它们相等,那么您执行相同数量的任何操作都会得到相同的结果。当它是单倍单然后转换为双倍时,它们是不同的。
trunc
0x40A25400_00000000
0x40A25200_00000000
这使您的代码工作(对于这两个特定值)。
false