3

When working with floating-points one should use

a <= 0.0

instead of

a == 0.0

to make sure that you get the desired behaviour, as there is the problem with round-off errors when using floating-point variables.


But when using other variable types like int could it be useful to do the same? Like you have a for loop iterating over an int variable (like an index) and when it gets to a number it should do something. Should you then set the comparison to be >= instead of == when it should result in the same output? Like could there ever be a case where the == is not evaluated in the following case:

for (int i = 0; i < 10; i++)
{
    if (i == 5)
    {
        break;
    }
}

And that it would be "safer" to do the following instead:

for (int i = 0; i < 10; i++)
{
    if (i >= 5)
    {
        break;
    }
}

If there is no difference between the two when it comes to coding "safe" is there any performance or readability difference or other thing that can make one choose between the ways to code?

Tried to google this but couldn't find anything stating either way. But that might have to do with the problem with searching for operators.

Am I too paranoid for asking this?

  • Should change `a = 0` to `a == 0.0`, right? – Fiddling Bits Oct 22 '18 at 18:09
  • @FiddlingBits Correct, I've fixed that now! – BitGen01100000 Oct 22 '18 at 18:12
  • 1
    `==` means something distinctly different from `>=`, so whether one is "safer" than the other depends on what your code is doing with the result. It's not a rule you can apply blindly. – John Bode Oct 22 '18 at 20:01
  • Add the line `if(good_reason_to_skip_this)continue;` at the top of the code inside your `for` loop, and maybe put in a bunch more stuff between that and the `if(i==5)` and you've got the recipe for an annoying bug. But I don't think `<=` is the right way to guard against that. I'd be tempted to use an assert instead, or rewrite the loop. It sounds like you might want two loops if you always break when `i` is `5` – Tim Randall Oct 22 '18 at 20:03
  • The integer 5 is always 5. Don't worry about it sometimes being 6. `if (i == 5 )` has a clearer intent, if that's what you mean. On the other hand, if the value you are checking against might be negative, then `if (i >= limit)` *is* required, and again the intent is clearer. For floating point, using `<=0` instead of `==0` is at best only a partial solution in most cases, and entirely unnecessary in others. The correct solution to round-off error is highly context-dependent and requires an understanding of the problem domain. – rici Oct 22 '18 at 20:49

3 Answers3

2

The premise of the question is wrong; blindly using a <= 0.0 instead of a == 0.0 is not a valid practice with floating point. See How dangerous is it to compare floating point values? for a treatment of the topic.

With that said, there are some cases where use of inequality relational operators are "more hardened" than use of the equality operator, and vice versa. In general, I would recommend against it since it's likely to give you a false sense of safety; for example, in the example in your question with i==5 vs i>=5, the compiler is likely to be able to prove they're the same, and optimize either to the other if needed. This means it will not necessarily do anything to protect you against stack overflows or neutrinos or any other cause by which the value of i might become something other than 0..5 outside of the defined semantics of the language.

There are also some cases where use of equality is defined by inequality is not, particularly involving pointers. If pos and end are both pointers, pos==end is well-defined as long as they are both valid. But if they are both null, while pos==end is well-defined and true, pos>=end is undefined behavior. Likewise if they both point into different arrays (in particular if end points to a sentinel not part of your array), pos==end will always be false, but pos>=end is undefined behavior.

I also find it misleading to write if (i>=5) when you know i>5 is logically impossible - it makes the reader stop to think about whether it's possible, and if not, why you wrote it that way instead of if (i==5).

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
1

The answer is, it depends. If you have a loop like this:

for (int i = 0; i < 10; i++)
{
    if (i == 5)
    {
        break;
    }
}

Then there is no danger in i skipping 5.

On the other hand, if you have something like this:

volatile int i;

void interrupt(void)
{
    i++;
}

void foo(void)
{
    for (i = 0; i < 10; i++)
    {
        if (i == 5)
        {
            break;
        }
    }
}

Then i may change outside the normal flow of the program (e.g. because of an interrupt). In this case >= would be prudent.

Fiddling Bits
  • 8,712
  • 3
  • 28
  • 46
  • The second situation you describe sometimes can't be fixed with >= because you don't always break on conditions, you may be doing something else if i == 5 and then keep the loop going, so, in that case, the "safety problem" doesn't come with integers but with volatile – Franco Fusaro Oct 22 '18 at 18:24
1

Like could there ever be a case where the == is not evaluated

No, using == is safe. Integers represent all values within the range of the integer type used accurately. There are no surprises.

Should you then set the comparison to be >= instead of ==

As the result is the same, you can do both but I would find >= confusing. So for readability I prefer ==

is there any performance . . . that can make one choose between the ways to code

You can't tell by looking at the C code. It depends on the system (CPU) used. In general I would however doubt that you would experience any major difference.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63