单元测试浮点信号处理库时的误差界限

时间:2012-09-13 10:27:43

标签: c++ unit-testing floating-point signal-processing

我有一个符合规范的信号处理库。但是,我已经确定了一些重构的好地方。我有意将单元测试整合到我的工作流程中一段时间​​,这看起来是一个尝试非平凡代码的好机会。这样我可以测试重构后输出几乎相同。

我正在试验catch作为测试框架,但是,这个细节可能无关紧要(因为我可以收集)所有测试框架都取决于运算符的结果,即

REQUIRE(i_x == 2)

但是,对于浮点数据,需要进行某种形式的错误边界检查。 。

const float target = 2.000f;
const float tolerance = 0.000005f;
const float err = target*tolerance;
REQUIRE( (f_x > target-err) && (f_x < target+err) )

对于每次编写的测试,这都会很快变得难看,所以当然,我可以创建一个(模板化的)全局函数,返回bool给定xtarget和{{ 1}}作为参数。

这是其他人这样做的方式吗?这是最佳做法还是我错过了一招?

1 个答案:

答案 0 :(得分:4)

测试对上下文非常敏感。你建议的测试测试相对误差。从本质上讲,你在这种特殊情况下断言:

  • 正常,可接受的代码更改可能会在每个结果中产生相对于结果较小的偏差。
  • 错误可能会产生相对于结果不小的偏差。

总的来说,我认为第二个断言通常是安全的。 “随机”代码更改可能会在至少某些值上产生巨大差异。但是,可能有一些应用程序可以很好地处理浮点数,在这种情况下,小偏差可能会导致结果超出规范。例如,假设您有一个arcsine例程,该例程返回的结果与正确的结果略有不同:当正确的结果为1时,它返回1 + 2 -23 。之后,此结果x为用在sqrt(1-x*x)之类的表达式中。对于所有数学上正确的arcsine值(对于实数输入),此表达式是真实的,但是,如果x略大于1,则它会尝试取负数的平方根,并发生错误。所以你必须决定第二个断言是否适合你的应用。

第一个断言更值得怀疑。浮点运算中的误差源并不总是与最终结果成比例。例如,考虑采用某些输入信号的离散傅立叶变换(DFT)。对于几乎每个输出数字,每个输入数字贡献一些部分。根据偶然情况,某些单独的输出数字将接近零。但是,它们中的错误可能与输入中的大数字成比例。因此,对这些输出数量应用相对误差测试将产生错误的错误指示。相反,有必要允许输入以某种方式缩放的错误。