【问题标题】:Floating point comparison in general unit tests一般单元测试中的浮点比较
【发布时间】:2016-01-14 07:53:45
【问题描述】:

我知道这个问题已经讨论了很多。我在网上搜索并自己提出了一个算法。我想知道它是否可以作为在一般单元测试(不是一些严肃/专业的数字测试)中正常工作的默认实现。

bool equal_to(double x, double y) {
  using limits = std::numeric_limits<double>;
  auto mag_x = std::abs(x);
  auto mag_y = std::abs(y);
  if (mag_x < mag_y) {
    std::swap(x, y);
    std::swap(mag_x, mag_y);
  }
  auto eps = limits::epsilon() * mag_x;
  auto lb = x - eps;
  auto ub = x + eps;
  return lb < y && y < ub;
}

刚刚发现一个漏洞。最后一条语句应该是

return (x == y) || (lb < y && y < ub);

万一equal_to(0, 0);

【问题讨论】:

  • 你有什么问题?
  • @DanielDaranas 我想知道这个算法是否存在任何重大缺陷,使其不适合在一般单元测试中用于比较浮点值。
  • 交换的意义何在? eps 只需要 std::max(mag_x, mag_y) 并且如果 x 在 y 的 eps 内,那么 y 也在 x 的 eps 内。等效地,abs(x-y)&lt;eps.
  • @MSalters 是的,你是对的 :-)
  • @MSalters 我想我只是不想做减法。所以我使用了交换。

标签: c++ algorithm unit-testing floating-point numeric


【解决方案1】:

不,这还不够。您的 eps 太低,可能应该乘以用于生成 xy 的步骤数(尽管这些错误经常取消,但不能保证)。

此外,您的舍入效果可能会因灾难性取消而被放大。如果 x 大约为 0.1,因为它被计算为 10.0 - 9.9,那么您应该使用 limits::epsilon * (10+9.9)。你太乐观了大约 100 倍。

【讨论】:

  • 好吧,我想没有适用于所有情况的通用解决方案。不然标准库应该已经在&lt;numeric&gt;什么的里面提供了这样的东西。
猜你喜欢
  • 2022-12-14
  • 2012-06-03
  • 2013-02-01
  • 2015-12-25
  • 1970-01-01
  • 2011-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多