【问题标题】:Is if(double) valid C++?if(double) 是有效的 C++ 吗?
【发布时间】:2010-09-22 07:31:58
【问题描述】:

我刚碰到这行代码:

if( lineDirection.length2() ){...}

其中length2 返回double。 0.0 等于 0、NULL 和/或false,这让我有点困惑。

这是 C++ 标准的一部分还是未定义的行为?

【问题讨论】:

    标签: c++ floating-point implicit-conversion


    【解决方案1】:

    这是一种非常标准的行为(布尔转换)

    $4.12/1 - “算术右值, 枚举、指针或指向的指针 成员类型可以转换为 布尔类型的右值。一个零值, 空指针值或空成员 指针值转换为假; 任何其他值都将转换为 true。”

    【讨论】:

      【解决方案2】:

      是 - 与零 (0.0) 进行比较,如果结果正好为零,则返回 false,否则返回 true。

      该行为继承自 C,它以相同的方式处理等效比较。

      【讨论】:

        【解决方案3】:

        值得注意的是,这段代码对于浮点表示非常脆弱。当且仅当浮点值恰好为 0 时,此代码才有效,这在大多数情况下实际上不太可能。在这种特殊情况下可能不是这样,但如果是这样,肯定应该记录/评论。

        在几乎所有其他情况下,您需要确定一个"epsilon value",它定义了您认为“相同”的浮点数范围 - 否则你的比较很可能会让你在角落里感到惊讶(而且通常不是那么 -角落)案例。

        【讨论】:

        • +1 用于指出代码的脆弱性。这将在许多可能不明显的条件下中断:double d = 0.0 / -1.0; if (d) 产生错误,如-0.0 != 0.0,对于许多其他可能产生足够接近 0 值但不是完全 0.0
        • 只是为了确定。代码 "double x=0.0;if(x){cout
        • @David Rodríguez - dribeas:不,-0.0 == 0.0,即使位模式不同。这是至关重要的。当1.0/x 会导致除以零时,表达式(x==0.0 || (1.0/x))计算1.0/x
        • @Benoît:因为这是一个编译时间常数,编译器很可能会在那里注入一个真正的0.0。当有任何算术运算时就会出现问题,这是因为浮点数的精确比较很难在许多情况下失败。阅读这篇文章:docs.sun.com/source/806-3568/ncg_goldberg.html
        • @David Rodríguez - dribeas:真的很令人惊讶,因为 GNU 文档的说法正好相反。见gnu.org/s/libc/manual/html_node/Infinity-and-NaN.html(最后一行)
        【解决方案4】:

        当您在不使用运算符的情况下进行比较时,您是在“与真”进行比较,因此每个变量类型都会被检查为布尔值(简单情况)或其他类型。数值变量类型的 false 值定义为“0”、“0.0”左右,因此当您将它们“与 true”进行比较时,您的比较将返回 false。

        【讨论】:

          【解决方案5】:

          如果 length2 返回 0.0,它将被视为 false。但是通过这种比较,您可能会得到令人惊讶的结果。在浮点比较期间,最好使用 MadKeithV 建议的 epsilon 值。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-01-13
            • 1970-01-01
            • 2016-06-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多