比较C中的浮点数进行单元测试

Mic*_*len 4 c floating-point arithmetic-expressions

所以我正在使用CUnit进行单元测试.我期待类似的东西

float x;
x = atof("17.99");
Run Code Online (Sandbox Code Playgroud)

我想用断言测试这个; 显然我可以用一些小ε

CU_ASSERT(abs(x - atof("17.99")) < epsilon);
Run Code Online (Sandbox Code Playgroud)

不过我正在考虑

r = atof("17.99");
CU_ASSERT(0 == memcmp(&x, &r, sizeof(float));
Run Code Online (Sandbox Code Playgroud)

这看起来确实有效.我希望使用它来避免必须根据值在每个测试中手动设置epsilon.在上述情况下,1e-6应该足够了; 但是如果使用1e-6的epsilon值为1e-10可能不会出现问题.开发人员拥有的选择越多,就越容易出错.

我的问题是:这种技术在posix系统上是否应该稳定?也就是说,如果要比较的两个浮点数是由完全相同的步骤生成的,那么它们的内部表示应完全相同.

编辑:更重要的是,我最终想要一个CU_ASSERT_FLOAT_EQUAL宏.

Ian*_*dby 6

比较浮点值很难.在弦乐中混音不会让事情变得更好,当然也不会引入epsilon会有的少量回旋余地.

看看这篇文章:比较浮点数,2012版.对于我的钱,ULP是要走的路.有一些讨厌的边缘情况,但你可能可以忽略它们中的大部分.

编辑:5月31日 考虑到这一点,我想你要问的是"如果在测试函数和被测函数中使用完全相同的步骤计算浮点数,答案是否完全相同 -所以我不需要担心+/-一些小错误?"

答案是肯定的,它们将是相同的.但是在这种情况下,您已经使单元测试毫无意义,因为如果测试代码中存在错误,那么测试函数中必然会出现同样的错误.

顺便说一下,不要因使用memcmp(&x,&y,sizeof(x))而分心.这只测试在两个值中设置完全相同的位.如果这是真的,那么x == y必然是真的.坚持x == y.