Issue
This Content is from Stack Overflow. Question asked by Vitor Niskier
leap_year = int(input('Year: '))
initial_year = leap_year
while True:
leap_year += 1
if leap_year % 4 == 0 and (leap_year % 100 == 0 and leap_year % 400) == 0:
print(f'The next leap year after {initial_year} is {leap_year}')
break
Can someone explain to me how this: if leap_year % 4 == 0 and (leap_year % 100 == 0 and leap_year % 400) == 0:
is different from this: if leap_year % 4 == 0 and leap_year % 100 == 0 and leap_year % 400 == 0:
Solution
It’s confusing how there’s an == 0
at the end, which is functionally the same as putting not
before that part. It’s also confusing how leap_year % 400
isn’t directly compared against anything, unlike the other modulo operations.*
It’d be clearer to rewrite it:
leap_year % 4 == 0 and not (leap_year % 100 == 0 and leap_year % 400 != 0)
If we apply De Morgan’s law, it might be even clearer:
leap_year % 4 == 0 and (leap_year % 100 != 0 or leap_year % 400 == 0)
Lastly, you could remove the parentheses at this point, but it’s better for readability to keep them.
Now it should be obvious how it differs from the other condition you mentioned.
* What actually happens there is that the and
evaluates leap_year % 100 == 0
and if it’s falsy, it yields the result, i.e. False
; if it’s truthy, it yields the result of leap_year % 400
, i.e. an int in range(0, 400, 100)
. That gets compared against the == 0
at the end, and for False
it works because False == 0
.
This Question was asked in StackOverflow by Vitor Niskier and Answered by wjandrea It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.