Confused about logical statements in C++

  • Context: C/C++ 
  • Thread starter Thread starter torquerotates
  • Start date Start date
  • Tags Tags
    C++ Confused
Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
3 replies · 2K views
torquerotates
Messages
207
Reaction score
0
Maybe this should belong in the logic section. But since this is C++, ill put it here.

bool isLeapYear( int y)
{
return y%4==0 && y % 100 !=0 || y% 400==0 ;
}



They said it returns when y is divisible by 4 but not by 100 unless it is also divisible by 400.

This is a bit confusing since I thought that statements are binary. that is its either A and(BorC) or (AorB)andC. I mean we get statements like (A and B and B) b/c [A and (B and C)]=[A and B and C]. Same thing for the or operator. But I can't see how (A and B or C) results from a binary logical statement involving two sets.

Do they mean (y%4==0 && y % 100 !=0 || y% 400==0) is the same as

(y%4==0) && (y % 100 !=0 || y% 400==0)?

It would make a lot more sense b/c
(y%4==0) && (y % 100 !=0 || y% 400==0) is the same as

(y%4==0 && y % 100 !=0) ||(y%4==0 && y% 400==0)

which is the same as the statement:y is divisible by 4 but not by 100 unless it is also divisible by 400.
 
Physics news on Phys.org
It works. Let's look at 100 as an example and 800.

100:

First, C++ checks if y % 4 == 0. 100 % 4 == 0, so this is true.

Then, it checks if y % 100 != 0. This is false.

true AND false is false.

Then, it checks if y % 400 == 0. 100 % 400 == 100 != 0, so this is false.

false OR false is false, so the function returns false.

800:

First, C++ checks if y % 4 == 0. 800 % 4 == 0, so this is true.

Then, it checks if y % 100 != 0. This is false.

true AND false is false.

Then, it checks if y % 400 == 0. 800 % 400 = 0 == 0, so this is true.

false OR true is true, so the function returns true.
 
Last edited:
torquerotates said:
Do they mean (y%4==0 && y % 100 !=0 || y% 400==0) is the same as
(y%4==0) && (y % 100 !=0 || y% 400==0)?
No! The initial expression is the same as

(((y % 4 == 0) && (y % 100 != 0)) || (y% 400 == 0))

A fully parenthesized version of this expression is

((((y % 4) == 0) && ((y % 100) != 0)) || ((y% 400) == 0))


The expression (y%4==0 && y % 100 !=0 || y% 400==0) has no parentheses. There is a lot of ambiguity in that expression. One has to look to the precedence table to resolve this ambiguity. Modulus takes precedence over every other operation in this expression, so the first step in resolving the ambiguity is to group the modulus operations:

((y % 4) == 0 && (y % 100) != 0 || (y% 400) == 0)

Equality and inequality come next in precedence, resolving the expression to

(((y % 4) == 0) && ((y % 100) != 0) || ((y% 400) == 0))

Here we have something of the form A && B || C. Logical and takes precedence over logical or, perhaps by way of extension that multiplication takes precedence over addition (2*3+4 is 10, not 14). With this rule, A && B || C is the same as (A && B) || C, or

((((y % 4) == 0) && ((y % 100) != 0)) || ((y% 400) == 0))


That fully-parenthesized version leaves no doubt as to the meaning. My personal rule: Don't rely on the precedence table except where it's patently obvious. 2*3 + 4 is patently obvious. It's 10, no parentheses are needed. Beyond that, it's not obvious. I tend to use lots of parentheses to remove all doubt. On the grounds that arithmetic operators taking precedence over the comparison operators is fairly obvious, I might write the above as

(((y % 4 == 0) && (y % 100 != 0)) || (y% 400 == 0))


Note that even though your interpretation is incorrect, it still works here. The reason is that 100 and 400 are multiples of 4.
 
Be aware that C and C++ will "short circuit" boolean expressions.

in the case of

if (A && B) {...}

A is checked first, and B will never be evaluated if A is false, which can have side effects if B is a function that updates a state.

Also be aware the order of execution is not guaranteed under C or C++. Only the order of precedence, and order of binding is guaranteed.

a+b+c is parsed as a+(b+c) because of right to left binding on the + operator, but the compiler can compute B and C in any order it wants to. Again this can have side effects where B and C are [STRIKE]not simple numbers[/STRIKE] interdependent.
 
Last edited: