比较两个可能是 NaN 的变量相等性的正确方法是什么?

What is the proper way to compare equality of two variables that could be NaN?

提问人:roulette01 提问时间:3/17/2023 更新时间:3/17/2023 访问量:85

问:

我在我正在使用的代码库中发现了一个错误,他们使用 检查两个双精度 () 的相等性,但这 2 个变量可能是 .first, secondfirst == secondNaN

如果两个变量都是,则相等将是 。NaNfalse

所以我目前的解决方案是代替

first == second

我们使用

(first == second || (std::isnan(first) && std::isnan(second))

有没有更简单的方法可以做到这一点?

C++ 平等 isnan

评论

0赞 user1095108 3/17/2023
哈哈,这可能不是一个错误,只是一个比你更有经验的程序员。
0赞 roulette01 3/17/2023
@user1095108我的意思是这不是代码库中检查的预期行为,所以这绝对是一个错误
1赞 Eric Postpischil 3/17/2023
如果两个项目都是 NaN,还是仅当两个项目都是相同的 NaN(具有相同的符号和有效载荷并且都发出信号或都安静)时,您想要“真实”结果?
0赞 Jerry Coffin 3/17/2023
NaN 的全部意义在于它不是一个数字。比较两个应该是数字的事物的代码不应期望比较会产生两个不是数字的事物。true
0赞 roulette01 3/17/2023
@EricPostpischil我认为是前者。此检查是在检查中完成的,下面是基础类的属性。出于某种原因,原始开发人员选择将这些变量初始化为operator==first, secondstd::numeric_limits<double>::quiet_NaN()

答:

3赞 Silvio Mayolo 3/17/2023 #1

首先,评估如果两个值均为 NaN,则是否确实希望条件运行。NaN 是一个很好的指标,表明事情出了大问题,而不是 null 或空状态。如果意图是有两个可能存在也可能不存在的值,您可以考虑更改它们以明确这一点。否则,如果你确定,那么你所做的是正确的。让 NaN 比较起作用并没有什么神奇的技巧,即使你确实找到了一个抽象出来的库,它仍然会完全按照你刚才在后台所做的工作。std::optional<double>

评论

0赞 roulette01 3/17/2023
无论出于何种原因,我正在检查的一些变量都初始化为 NaN,不确定为什么它以这种方式设计。
0赞 JohnFilleau 3/17/2023
@roulette01听起来你的第一步是找出为什么它被设计成这样
1赞 Martin York 3/17/2023 #2

与其使用过于笼统的表达方式:

(first == second || (std::isnan(first) && std::isnan(second))

使用命名函数从以下方面开始:

inline bool areFloatPointComparablyEquivelent(double lhs, double rhs)
{
      // Add a long very detailed explanation of why you need
      // This expression (in two years you will not be here and the
      // the next maintainer may own an axe and know where you live).

      // The exact reason or expression is not that important.
      // What is important (if not trivial, obvious) is a WHY.
      return result;
}

现在,在您需要执行此测试的任何地方使用此自记录功能(即使它仅在一个地方)。