# [Tutor] [Fwd: Re: n.isalnum() is failing]

Terry terry.kemmerer at gmail.com
Wed Jul 4 21:17:32 CEST 2007

```Thanks Alan,

I managed to get totally confused by the different definitions of
calculating a leap year. The book (Core Python)
described the exercise thus:

"Modulus.  Determine whether a given year is a leap year, using the
following formula: a leap year is one that is divisible by four, but
not
by one hundred, unless it is also divisible by four hundred."

That sounded to me like:  y % 4 ==0 and (y % 100==1 or y % 400==0)
Then, after reading it ten more time I became uncertain and decided to
find another definition and compare them.
I found U.S. Naval Observatory:

"According to the Gregorian calendar, which is the civil calendar in use
today, years evenly divisible by 4 are leap years, with the exception of
centurial years that are not evenly divisible by 400."

Comparing the two, confused me a bit more, and I ended up ignoring the
first definition, saying to myself, all 4th years are leap years, unless
they are y % 100 ==0 AND y % 400==1. That sounded clearer....but,
evidently, not correct. Ha Ha Ha

I liked the way you directly formed it. It was more like my old IF-THEN
statements.....to the point and we're out of here.

def isLeapYear(y):
if y % 4 == 0: return True
if (y % 4 == 0) and not (y %100 == 0): return True
else: return False

I am checking out your python tutor web site at
http://www.freenetpages.co.uk
It looks like it surpasses by far other's I have checked out. Great job!

Thanks for the correction and the methodology!

Terry

> def isLeapYear(y):
>    if y % 4 == 0:
>        if y % 100 == 0 and y % 400 == 1:

Not quite. y%400 == 1 will only be true for years
like 2001, 1601 etc!
You need to invert the test so y % 400 != 0.  (or use not)
But there is a more direct way:

Lets recap:

1) A year that is divisible by 4 is a leap year. (Y % 4) == 0
2) but: a year that is divisible by 100 is not a leap year. (Y % 100)
!= 0 3)
3) however a year that is divisible by 400 is a leap year. (Y % 400)
== 0

So a year that is divisible by 400 is *always* a leap year:

if y % 400 == 0: return True

Now we need a combined test for the other 2 cases.
If its divisible by 4 and not by 100 its a leap year:

if (y % 4 == 0) and not (y %100 == 0): return True

So we can combine the definitions to give:

def isLeapYear(y):
if y % 400 == 0: return True
if (y % 4 == 0) and not (y %100 == 0): return True
else: return False

Which is shorter and clearer IMHO.
(You could combine it into one line but I personally
think that would make the rules less clear.)

This is one of the cases where using multiple returns
makes the code clearer in my view.

> print "This program finds all leap years between any two
> dates.";print;print
>
> start = end = None
> while start == None:
>    try:
>        start = int(raw_input("Enter yyyy for beginning year : "))
>        end = int(raw_input("Enter yyyy for ending year : "))
>
>    except ValueError:
>        print;print "YEAR must be a integer number -- TRY AGAIN!"
>        start = end = None
>
> if 1 <= start < end:
>    print; print
>    for y in range(start, end + 1):
>            print y, "--leap year!"

Also the point of a predicate function is that it returns
a boolean value so you don;t need any intermediate
variables. You can just use it in the condition, like

if isLeapYear(y):
print y, '--leap year'

By using a predicate style name (isXXXXX) the code
becomes clearer than when you introduce an intermediate
variable where the reader then has to backtrack to see
what the test value is based on.

> 1900 --leap year!

This is wrong, 1900 is divisible by 100 but not by 400...

> 1904 --leap year!
> 1908 --leap year!
> ...
> 2000 --leap year!

Whereas 2000 is correct because it is divisible by 400.

HTH,

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/tutor/attachments/20070704/fdd911fb/attachment.html
```