【发布时间】:2011-06-07 00:58:40
【问题描述】:
今天我正在追查为什么我的程序会出现一些意外的校验和不匹配错误,在我编写的一些代码中,以包含 32 位校验和值的格式序列化和反序列化 IEEE-754 浮点值(这是通过对浮点数组的字节运行 CRC 类型算法来计算的)。
经过一番摸索后,我意识到问题在于 0.0f 和 -0.0f 具有不同的位模式(分别为 0x00000000 与 0x00000080(小端序)),但它们被 C++ 相等性视为等效-操作员。因此,发生校验和不匹配错误是因为我的校验和计算算法发现了这两个位模式之间的差异,而我的代码库的某些其他部分(使用浮点相等测试,而不是逐字节查看值) byte) 没有做出这种区分。
好吧,很公平——无论如何,我应该知道最好不要进行浮点相等测试。
但这让我想到,是否有其他 IEEE-754 浮点值被认为是相等的(根据 C == 运算符)但具有不同的位模式?或者,换一种说法,== 运算符究竟是如何决定两个浮点值是否相等的?新手我虽然它在他们的位模式上做了类似 memcmp() 的事情,但显然它比这更细微。
这是我的意思的代码示例,以防我上面不清楚。
#include <stdio.h>
static void PrintFloatBytes(const char * title, float f)
{
printf("Byte-representation of [%s] is: ", title);
const unsigned char * p = (const unsigned char *) &f;
for (int i=0; i<sizeof(f); i++) printf("%02x ", p[i]);
printf("\n");
}
int main(int argc, char ** argv)
{
const float pzero = -0.0f;
const float nzero = +0.0f;
PrintFloatBytes("pzero", pzero);
PrintFloatBytes("nzero", nzero);
printf("Is pzero equal to nzero? %s\n", (pzero==nzero)?"Yes":"No");
return 0;
}
【问题讨论】:
-
how-to.wikia.com/wiki/… 仅供参考,使用 epsilon 是浮点比较的前进方向。不切题,但对了解很有用。
-
NaN 可以采用任何一种方式(可能取决于编译器)。它们在内存中也可能不同,因为存在大量可能的 NaN(单精度为 2^24-1)。
标签: c comparison floating-point equality ieee-754