val!= std :: numeric_limits <double> :: infinity()或!isinf(val)或isfinite(val)

Kur*_*ehr 8 c++ nan infinity numeric-limits c++11

这可能是自行车脱落,但也许有一些有趣的东西让我失踪......

如果一个类初始化一个成员val,std::numeric_limits<double>::infinity()然后想要检查val是否已被更改为有效的东西(+/- inf在这里无效),这3种方法的权衡是什么,我是否错过任何其他有趣的方法来解决这个问题.(为了便于阅读,删除了const.)

bool IsInit() { return MinX != std::numeric_limits<double>::infinity(); }  // a

bool IsInit() { return !std::isinf(MinX); }  // b

bool IsInit() { return std::isfinite(MinX); }  // c
Run Code Online (Sandbox Code Playgroud)

现在代码是C++ 03,但是如何使用C++ 11,C++ 14和C++ 17来改变选项.例如,使用C++ 17,这段代码可能就是这样std::optional<double> val.或者安静NaN是一个更安全的赌注,只是因为+/- inf在未来变得有效?

当我在阅读此代码的补丁时出现了这个问题:

为便于参考:

相关类型:

Lou*_*ltz 4

仅当变量无法以其他方式获取特殊值时,使用这些特殊值作为初始化标志才有效。就数学运算而言,无穷大并不难获得,因为溢出也会得到它。所以这可能会有问题。如果不变量只是用户无法将此浮点值设置为该值,则使用安静的 NaN(如果可用)会更容易使用。

就这三种方法而言,只有方法“a”与初始值完全匹配。因此,如果不变式是只有初始值代表初始化值,那么这是最准确的方法。当然,这些方法从一开始就没有对保护不变量起到任何作用,这在我看来更重要:不变量是否或可以有效执行。

OGREnvelope虽然这并不是一个代码审查网站,但就github 上的类(似乎只是 AABB)的链接代码编辑而言,我认为应该注意以下几点:

  • -IsInit基于其代码 - 似乎意味着返回 AABB 是否实际上已由用户设置。不在于它是否处于其初始状态/价值,正如可以IsInit论证的那样(并误导了我相信)。IsValid就我个人而言,我更喜欢这个测试的名称。
  • 至于不变量实际上是什么,编辑本身似乎认识到有效的 AABB 的MinX值永远不应该大于 ,MaxX也不MinY应该大于MaxY。换句话说,在有效的 AABB 中,它们永远不应该被逆转。MinX应始终小于或等于MaxX(最小和最大 Y 变量相同)。
  • 使用反向无穷大值,可以:(a) 更容易潜在地增长 AABB 以包围其他 AABB(并且编辑演示了我所说的将代码行从 14 行减少到 4 行的意思);(b) 使其能够处理比使用max()和lowest()值更广泛的有效 AABB。
  • 事实上MinX, 、MaxX、MinY、MaxY成员变量是可公开访问的,这意味着IsInit不变量本身只是建议性的,因为没有封装来保护不变量。

在更广泛的背景下,NaN 是不合适的。不变量从来都不是真的MinX != std::numeric_limits<double>::infinity()。并且IsInit(如该代码中实现的)充其量是不完整的。在将其重命名为类似的上下文中IsValid,逻辑上更一致的实现是:

bool IsValid() const
{
    return !std::isnan(MinX) && !std::isnan(MinY) && MinX <= MaxX && MinY <= MaxY;
}
Run Code Online (Sandbox Code Playgroud)

通过此实现,有效的 AABB 是一个OGREnvelope其值都是有效数字(没有一个是 NaN)且其最小值必须分别小于或等于 X 和 Y 的最大值的 AABB。

  • 选项“a”的另一个优点是您可以在类中为常量指定一个有意义的名称(作为私有静态常量),以便“MinX != UNINITIALISED_VAL”测试更加清晰。 (2认同)