简体   繁体   中英

Setting and checking with a float constant

I know there are a lot of questions on here about why float equality comparison is usually a bad idea. I understand float representation issues, rounding issues, silent promotion of floats to doubles, the dangers in relying upon arithmetic at the bit level, etc. But it seems to me that this should be fine, and no questions I found seem to cover this:

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
    }
}

The output is as expected:

0
4

If I have -Wfloat-equal enabled (in gcc, but similar in other compilers), it will flag the comparison line as dangerous: comparing floating point with == or != is unsafe . And pretty much all the answers on here say not to use == or,=, period . But I don't see why it's a problem here. I'm only setting the constant once and re-using it everywhere else it's used, and there is never any manipulation of that constant (eg arithmetic). Am I missing something? What about 0.0f , even if not set as a constant?

As long as you're confident MARKER and its copies won't be altered by arithmetic functions or something, there's no issue doing a simple comparison.
Maybe consider not using -Wfloat-equal globally but disable warnings locally:

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

Or a portable equivalent: https://www.fluentcpp.com/2019/08/30/how-to-disable-a-warning-in-cpp/

You miss the reason when to use floats. You use floats to do math. As long you only compare float literals it is going to be alright. However as soon you do some manipulation on the numbers and compare them afterwards it is generally not going to be working (even though there are cases where it may be working) as floating point operations are not exact. That is what people mean when saying "Do not compare floats".

Further many compilers have flags for their specify floating-point behavior. For MSVC for instance have a look here . This makes it even more obvious that an exact comparison is never going to be a good idea.

If you want to mark floats like this you can certainly do it, however, I would suggest using std::numeric_limits<float>::min() as the marker value to be safe. Just be sure to not manipulate these values mathematically. Also consider that other developers may take the presence of a float as an indicator that it is valid to manipulate these values, which would not be good. As an alternative to that you may consider std::optional to mark whether the numbers are valid.

Just as a comment on the static : I would further suggest to drop the static as there really is no need for that and the word performance popped up somewhere. I would change that to look like this:

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
}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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