Date.gregorian_leap? code

from date.rb

Is a year a leap year in the Gregorian calendar?

All years divisible by 4 are leap years in the Gregorian calendar,

except for years divisible by 100 and not by 400.

def self.gregorian_leap? (y) y % 4 == 0 && y % 100 != 0 || y % 400 ==
0 end

Because of the precedence of && and || this is presumably parsed as
( y % 4 == 0 && y % 100 != 0 ) || y % 400 == 0
and I’m trying to think of reasons why it is coded as it is instead of,
say:
y % 4 == 0 && ( y % 100 != 0 || y % 400 == 0 )

Any suggestions?

On Dec 23, 2:42 pm, Colin B. [email protected] wrote:

from date.rb

Is a year a leap year in the Gregorian calendar?

All years divisible by 4 are leap years in the Gregorian calendar,

except for years divisible by 100 and not by 400.

def self.gregorian_leap? (y) y % 4 == 0 && y % 100 != 0 || y % 400 == 0 end

Because of the precedence of && and || this is presumably parsed as
( y % 4 == 0 && y % 100 != 0 ) || y % 400 == 0
and I’m trying to think of reasons why it is coded as it is instead of, say:
y % 4 == 0 && ( y % 100 != 0 || y % 400 == 0 )

I suppose because either one works:

irb> LEAP = [ 1796, 1804, 1896, 1904, 1992, 1996, 2000, 2004, 2008 ]
irb> NOLEAP = [ 1799, 1800, 1801, 1802, 1803, 1805, 1899, 1900, 1901 ]
irb> def test_leap
irb> LEAP.each{ |y| puts “BAD! #{y} must leap” unless yield y }
irb> NOLEAP.each{ |y| puts “BAD! #{y} musn’t leap” if yield y }
irb> end
irb> test_leap{ |y| y % 4 == 0 && y % 100 != 0 || y % 400 == 0 }
irb> test_leap{ |y| ( y % 4 == 0 && y % 100 != 0 ) || y % 400 == 0 }
irb> test_leap{ |y| y % 4 == 0 && ( y % 100 != 0 || y % 400 == 0 ) }

On Thu, Dec 24, 2009 at 3:20 AM, Phrogz [email protected] wrote:

On Dec 23, 2:42 pm, Colin B. [email protected] wrote:

Because of the precedence of && and || this is presumably parsed as
( y % 4 == 0 && y % 100 != 0 ) || y % 400 == 0
and I’m trying to think of reasons why it is coded as it is instead of, say:
y % 4 == 0 && ( y % 100 != 0 || y % 400 == 0 )

I suppose because either one works: …

It’s true that both variations give the same result. But using y = 2003:
y % 4 == 0 && y % 100 != 0 || y % 400 == 0
evaluates y % 4 == 0 as false and then (as far as I can see)
also evaluates y % 400 == 0 as false,
and what I’m not seeing is why one might do that:
if something isn’t exactly divisible by 4 it won’t be divisible by 400.
Hence my bracketed suggestion which stops at y% 4 == 0
for years which aren’t divisible by 4.

The code in date.rb isn’t wrong, because it gives the correct answers,
and won’t take much extra processing time to (from my point
of view) “unnecessarily” evaluate y% 400 == 0 even if y % 4 != 0,
so this is admittedly a (very?) minor point, but it’s bugging me
that I can’t think of a reason why one wouldn’t put the brackets in
to avoid evaluating y % 400 == 0 in cases where the calculation
already knows that y% 4 != 0

On Thu, Dec 24, 2009 at 5:25 AM, Colin B.
[email protected] wrote:

y % 4 == 0 && y % 100 != 0 || y % 400 == 0
so this is admittedly a (very?) minor point, but it’s bugging me
that I can’t think of a reason why one wouldn’t put the brackets in
to avoid evaluating y % 400 == 0 in cases where the calculation
already knows that y% 4 != 0

&& and || are both short-circuiting, so

x && y
will immediately return x if x is falsy (nil or false), will not
evaluate y at all in this case.

x || y
will immediately return x if x is trutth (anything other than nil or
false) and will not evaluate y at all in this case.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: Rick DeNatale - Developer - IBM | LinkedIn