1

I've been really clumsy and ran into a bug due to my own fault. Basically:

#include <iostream>

float a = 4.f;
float b = 6.f;

int main()
{
    if (!a < b)
    {
        std::cout << "a is not less than b";
    }
    else std::cout << "a is less than b";

    std::cin.ignore();
    return 0;
}

So this conditional if statement always evaluates to true. If I wrap it in brackets as !(a < b) it works. So I understand I need the brackets.

My question is how is my wrong example parsed?

if (!a < b)

a has float value 4.f, does it turn 4.f from float value to boolean value, which is true, and then negate it to false, and then compare the false boolean value to b, which is 6.f float? How would it go about comparing a false boolean value to a float value of 6.f? If it converts 6.f float to boolean value the 6.f would turn into true, and the statement would be if (false < true), which doesn't make sense. Is this the way it's working?

I'm not sure if it's turned to if (false < true) because:

float a = 4.f;
float b = -50.f;

int main()
{
    if (!a < b)
    {
        std::cout << "a is not less than b";
    }
    else std::cout << "a is less than b";

    std::cin.ignore();
    return 0;
}

Always ends up false. I thought that -50.f should be turned to true. On the other hand, if I assign to an intermediary variable it's a different case:

float a = 4.f;
float b = -50.f;

int main()
{
    bool temp = b;
    if (!a < temp)
    {
        std::cout << "a is not less than b";
    }
    else std::cout << "a is less than b";

    std::cin.ignore();
    return 0;
}

Now it's always true.

Thanks to user apple apple for figuring this out, it turns out it parses as follows:

if (!a < b)
if (!4.f < 6.f) // Changes 4.f float to false boolean
if (false < 6.f) 
if (0.f < 6.f) // Promotes false boolean to 0.f
Zebrafish
  • 11,682
  • 3
  • 43
  • 119
  • [Is the operation “false < true” well defined?](https://stackoverflow.com/q/26143976/1708801) may be helpful – Shafik Yaghmour Aug 04 '18 at 03:55
  • @ShafikYaghmour Thanks, reading now. Is that what is happening? Is it in the end turning into if (false < true)? Or something else? – Zebrafish Aug 04 '18 at 03:56
  • also [operator precedence](https://en.cppreference.com/w/cpp/language/operator_precedence) may help – apple apple Aug 04 '18 at 04:03
  • 3
    I think it's `(!a) < b` => `false < 6.f` => `0 < 6.f` – apple apple Aug 04 '18 at 04:06
  • @apple apple I think you're right, and is consistent with the further examples I gave. So it turns the first float into a boolean type, then when it compares against the float it promotes the boolean into a float, meaning it becomes a zero. Interesting. – Zebrafish Aug 04 '18 at 04:20

2 Answers2

3

Try printing !a

std::cout << !a;

Logically negating a positive (or negative) value in C++ will give 0. Since 0 is less than 4.0, it is true.

There is additional information in this answer.

Bill
  • 1,407
  • 10
  • 18
3

if you check the operator precedence, you can see !(Logical NOT) would be evaluate first, so

!a < b would be parsed as (!a) < b

since a != 0, (!a) => false

it becomes false < b which is same as 0 < b

apple apple
  • 10,292
  • 2
  • 16
  • 36