creturn-valuelogical-operatorslogical-orlogical-and

What do these return conditions do in a Boolean function?


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?


Solution

  • 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.