What do these return conditions do in a Boolean function?

411 views Asked by At

On codecademy there exists a course on C, which includes a project on how to make a calendar. This project includes a boolean function which decides if a given year is a leap year or not. Code:

bool is_leap_year(int year) {
    return (year % 4 == 0 && (year % 100 || year % 400 == 0));
}

Given my beginner understanding of operators and return statements, my reading of this code would be: "A given year will be a leap year if it is divisible by 4 AND 100 OR 400." But this would mean that 1992 wouldn't be a leap year, and 1900 would be, which is plainly wrong.

How come then, that when I run the code and input these years, it does return a correct answer?

2

There are 2 answers

9
ikegami On BEST ANSWER

You appear to think

x || y == 0

means

x == 0 || y == 0

But it doesn't.

x || y == 0 doesn't mean "x or y is equal to zero".

x || y == 0 means "x, or y is equal to zero".

Put more clearly,

x || y == 0 means "(x) is true or (y is equal to zero) is true".

Since true simply means non-zero in C,

x || y == 0

is equivalent to

x != 0 || ( y == 0 ) != 0

That means the formula checks if the year isn't divisible by 100.

year % 4 == 0 Year is divisible by 4.

year % 100 Year isn't divisible by 100.

year % 400 == 0 Year is divisible by 400.

(Year is divisible by 4) and ( (Year isn't divisible by 100) or (Year is divisible by 400) )

How this would normally be stated in English:

It's a leap year if it's divisible by 4, but not by 100. Except years divisible by 400 are leap years.

And here's how things are calculated:

year % 4 == 0 && (year % 100 || year % 400 == 0)
1992 % 4 == 0 && (year % 100 || year % 400 == 0)
       0 == 0 && (year % 100 || year % 400 == 0)
            1 && (year % 100 || year % 400 == 0)
            1 && (year % 100 || year % 400 == 0)
            1 && (1992 % 100 || year % 400 == 0)
            1 && (        92 || year % 400 == 0)
            1 &&                               1 
                                               1

The right-hand side of || isn't evaluated because its left-hand is true.

0
Vlad from Moscow On

This return statement

return (year % 4 == 0 && (year % 100 || year % 400 == 0));

can be equivalently rewritten like

return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));

or like

return (year % 4 == 0 && year % 100 != 0 ) || (year % 4 == 0 && year % 400 == 0));

The condition means that a leap year is divisible by 4 and either not divisible by 100 or divisible by 400. So 1992 is a leap year because it is divisible by 4 but not divisible by 100. And 1900 is not a leap year because though it is divisible by 4 but it also divisible by 100 and not divisible by 400. That is neither this condition (year % 4 == 0 && year % 100 != 0 ) nor this condition (year % 4 == 0 && year % 400 == 0)) is satisfied.