繁体   English   中英

使用浮点常量设置和检查

[英]Setting and checking with a float constant

我知道这里有很多关于为什么浮动相等比较通常不是一个好主意的问题。 我了解浮点数表示问题、舍入问题、将浮点数无声地提升为双精度数、在位级别依赖算术的危险等。但在我看来,这应该没问题,而且我发现的任何问题似乎都涵盖了这一点:

static const float MARKER = -500.0f; // some value well outside the range of valid values
std::vector<float> some_floats = {MARKER, 0.5f, 100.0f, 9.5f, MARKER, 0.f};
for (size_t i = 0; i< some_floats.size(); ++i) {
    if (some_floats[i] == MARKER) {             
       std::cout << i << std::endl;
    } else {
       // do some math
    }
}

output 符合预期:

0
4

如果我启用了-Wfloat-equal (在 gcc 中,但在其他编译器中类似),它会将比较行标记为危险: comparing floating point with == or != is unsafe 这里几乎所有的答案都说不要使用 == or,=, period 但我不明白为什么这是一个问题。 我只设置常量一次,然后在其他任何地方重复使用它,并且永远不会对该常量进行任何操作(例如算术)。 我错过了什么吗? 0.0f怎么样,即使没有设置为常量?

只要您确信MARKER及其副本不会被算术函数或其他东西改变,进行简单比较就没有问题。
也许考虑不在全球范围内使用-Wfloat-equal但在本地禁用警告:

    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wfloat-equal"
    /* your code */
    #pragma GCC diagnostic pop

或便携式等同物: https://www.fluentcpp.com/2019/08/30/how-to-disable-a-warning-in-cpp/

您错过了何时使用浮动的原因。 你用花车做数学。 只要你只比较浮点数就没问题。 但是,一旦您对数字进行一些操作并在之后比较它们,它通常不会起作用(即使在某些情况下它可能起作用),因为浮点运算并不精确。 这就是人们说“不要比较浮点数”时的意思。

此外,许多编译器都有用于指定浮点行为的标志。 例如,对于 MSVC,请查看此处 这使得更明显的是,精确比较永远不会是一个好主意。

如果你想像这样标记浮点数,你当然可以这样做,但是,为了安全起见,我建议使用std::numeric_limits<float>::min()作为标记值。 请确保不要以数学方式操纵这些值。 还要考虑到其他开发人员可能会将浮点数的存在视为可以有效操纵这些值的指示符,这并不好。 作为替代方案,您可以考虑 std::optional 来标记数字是否有效。

正如对static的评论一样:我进一步建议放弃 static,因为确实没有必要,而且性能这个词突然出现在某处。 我会把它改成这样:

const float MARKER = std::numeric_limits<float>::min();  // some value well outside the range of valid values
std::vector<float> some_floats = {MARKER, 0.5f, 100.0f, 9.5f, MARKER, 0.f};
for (size_t i = 0; i < some_floats.size(); ++i) {
    if (some_floats[i] == MARKER) {
        std::cout << i << std::endl;
    } else {
    // do some math
}

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM