Confused about logical statements in C++

  • Context: C/C++ 
  • Thread starter Thread starter torquerotates
  • Start date Start date
  • Tags Tags
    C++ Confused
Click For Summary

Discussion Overview

The discussion revolves around the logical statements used in a C++ function to determine leap years. Participants explore the interpretation of the logical expression and its implications in programming, particularly focusing on operator precedence and the evaluation of boolean expressions.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant presents a C++ function for determining leap years and expresses confusion over the logical expression used, questioning how it can be interpreted in terms of binary logic.
  • Another participant provides examples using specific years (100 and 800) to illustrate how the function evaluates the logical expression step by step, confirming that it works as intended.
  • A different participant clarifies that the original expression is equivalent to a fully parenthesized version, emphasizing the importance of operator precedence in resolving ambiguities in logical statements.
  • This participant also shares a personal rule about using parentheses to avoid confusion, suggesting that relying solely on precedence tables can lead to misunderstandings.
  • Another participant notes the concept of "short-circuiting" in boolean expressions in C and C++, explaining that the evaluation order can affect program behavior, particularly when side effects are involved.
  • They also mention that while the order of precedence is guaranteed, the order of execution is not, which can lead to unexpected results if not properly managed.

Areas of Agreement / Disagreement

Participants express differing interpretations of the logical expression's structure and its implications. While some agree on the importance of parentheses for clarity, others maintain that the expression functions correctly as written. The discussion remains unresolved regarding the best practices for writing such expressions.

Contextual Notes

Participants highlight the ambiguity in logical expressions without parentheses and the potential for confusion due to operator precedence. There is also mention of the implications of short-circuit evaluation in boolean expressions, which can affect program behavior.

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.
 
Technology 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:

Similar threads

  • · Replies 5 ·
Replies
5
Views
3K
  • · Replies 11 ·
Replies
11
Views
2K
Replies
2
Views
2K
  • · Replies 5 ·
Replies
5
Views
2K
  • · Replies 17 ·
Replies
17
Views
4K
  • · Replies 2 ·
Replies
2
Views
4K
Replies
1
Views
1K
Replies
1
Views
3K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 4 ·
Replies
4
Views
2K