今天我在追踪我的程序为什么会收到一些意外的校验和不匹配错误。这些错误出现在我编写的代码中,用于序列化和反序列化IEEE-754浮点值,以包括32位校验和值(该值通过在浮点数数组的字节上运行CRC类型算法来计算)的格式。
经过一番思考,我意识到问题在于0.0f和-0.0f具有不同的位模式(分别是0x00000000和0x00000080(小端),但它们被C++等号运算符视为相等)。因此,校验和不匹配错误发生了,因为我的校验和计算算法捕捉了这两个位模式之间的差异,而我的代码库中某些其他部分(使用浮点等式测试,而不是逐字节查看值)没有做出这种区分。
好吧,说得对——我应该知道不要进行浮点等式测试。
但是这让我想到了,是否还有其他IEEE-754浮点值被认为是相等的(根据C == 运算符),但具有不同的位模式?或者换句话说,== 运算符如何确定两个浮点数是否相等?新手我认为它正在执行类似于memcmp()的操作,但显然它比那更微妙。
以下是我上面所说的代码示例,以防我没有表达清楚。
经过一番思考,我意识到问题在于0.0f和-0.0f具有不同的位模式(分别是0x00000000和0x00000080(小端),但它们被C++等号运算符视为相等)。因此,校验和不匹配错误发生了,因为我的校验和计算算法捕捉了这两个位模式之间的差异,而我的代码库中某些其他部分(使用浮点等式测试,而不是逐字节查看值)没有做出这种区分。
好吧,说得对——我应该知道不要进行浮点等式测试。
但是这让我想到了,是否还有其他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;
}