[comp.misc] Julian day numbers

J_Otto_Tennant@cup.portal.com (04/24/91)

In the introductory chapter of _Numerical_Recipies_, programs are 
presented for the calculation of the Julian day number given a 
date in the form of month/day/year, and vice-versa.

The key trick, as described in a recent article in "Dr. Dobb's",
is to renumber months so that February is last.  Given that wonderful
hack (which numbers March as "4" and February as "15"), the next step
is given as:

	JULDAY = INT(365.25*JY)+INT(30.6001*JM)+ID+1720995

The "magic number" 365.25 is easy to understand.  The magic number
1720995 can be figured out (given the renumbering of the months.)
The number 30.6001 is somewhat less easy to understand.

From my point of view, there are two aspects to the incomprehensibility
of 30.6001.

First, why is the constant 30.6001?  JM ranges from 4 to 15.  If we
view the constant 30.6001 as (30.6 + 0.0001), the 0.0001 term is
completely irrelevant to the calculation.  Why, in a book as
careful and accurate as _Numerical_Recipies_ would there be such
an irrelevant part of a constant?

Second, "30.6" works.  Empirically, there are only 12 cases, and
the cases work.  Was this number derived empirically?  Did the
authors, or possibly Zellar, just fiddle with constants until one
worked?  ("30.59_" does not work, by the way.)  Or is there some
derivation of the number?

moews@math.berkeley.edu (David Moews) (04/25/91)

In article <41601@cup.portal.com> J_Otto_Tennant@cup.portal.com writes:
|...
|	JULDAY = INT(365.25*JY)+INT(30.6001*JM)+ID+1720995
|...
|First, why is the constant 30.6001?  JM ranges from 4 to 15.  If we
|view the constant 30.6001 as (30.6 + 0.0001), the 0.0001 term is
|completely irrelevant to the calculation.  Why, in a book as
|careful and accurate as _Numerical_Recipies_ would there be such
|an irrelevant part of a constant?...

The number 30.6 (= 153/5) does not have a terminating binary representation.
As a result, if you just wrote `30.6' you might get a floating-point number
that was actually a little smaller than 30.6.  Then when you took INT(30.6*5) 
you might get 152 instead of 153, which would be incorrect.  Adding a small
fudge factor like 0.0001 prevents this.
--
David Moews                           moews@math.berkeley.edu

fisher@sc2a.unige.ch (04/25/91)

In article <41601@cup.portal.com>, J_Otto_Tennant@cup.portal.com writes:
> In the introductory chapter of _Numerical_Recipies_, programs are 
> presented for the calculation of the Julian day number given a 
> date in the form of month/day/year, and vice-versa.
> 
> The key trick, as described in a recent article in "Dr. Dobb's",
> is to renumber months so that February is last.  Given that wonderful
> hack (which numbers March as "4" and February as "15"), the next step
> is given as:
> 
> 	JULDAY = INT(365.25*JY)+INT(30.6001*JM)+ID+1720995
> 
> [...]
>
> From my point of view, there are two aspects to the incomprehensibility
> of 30.6001.
> 
> [...]

It's easily understood:  as the "year" starts with March you want to add
nothing for March, 31 days for April, 31+30 days for May, etc.  Taking the
INT( (NUM(Month)-NUM(March))*30.5 + 0.5) gives you alternating months of
31 and 30 days.

But every five months, you need to add an extra day, and substract 0.5 from
the original offset of 0.5.  This means you add a half day every five month,
or 0.1 every month.  This is why you take 30.6 instead of 30.5.

Now depending on the hardware (in some cases the software), the result of
30.6 * 5 is 153.0 or 152.99999...  Small difference, but the resulting INT()
changes.  That is the reason for the 30.6001  (INT(JM*30.6+0.001) would work
also, of course).

  Month NUM(Month)  NUM*30.6001      Prev. months   Last month

   Mar.     4        122.4004                0       (28/29)
   Apr.     5        153.0005 *             31         31
   May      6        183.6006               61         30
   Jun.     7        214.2007               92         31
   Jul.     8        244.8008              122         30
   Aug.     9        275.4009              153         31
   Sep.    10        306.0010 *            184         31
   Oct.    11        336.6011              214         30
   Nov.    12        367.2012              245         31
   Dec.    13        397.8013              275         30
   Jan.    14        428.4014              306         31
   Feb.    15        459.0015 *            337         31

The needed column is the total of days in the previous months, given by
INT(NUM(Month)*30.6001) - 122.  Of course, the 122 is included in the
constant 1720995 in the example.

NOTE: the example works only from 1. March 1990 to 28. Feb. 2100...

Regards,

Markus Fischer, Dept of Anthropology, Geneva CH

chl@cs.man.ac.uk (Charles Lindsey) (04/25/91)

In <41601@cup.portal.com> J_Otto_Tennant@cup.portal.com writes:

>First, why is the constant 30.6001?  JM ranges from 4 to 15.  If we
>view the constant 30.6001 as (30.6 + 0.0001), the 0.0001 term is
>completely irrelevant to the calculation.  Why, in a book as
>careful and accurate as _Numerical_Recipies_ would there be such
>an irrelevant part of a constant?

The calculation has to be performed in floating point. It may be that in
some floating point formats a number input as 30.6 gets stored as
30.5999999999999999. Looks like the extra .0001 was to make sure this didn't
happen.

J_Otto_Tennant@cup.portal.com (04/29/91)

This is a summary of the replies I have received in response to my post.

A number of people observed that the "0.0001" part of "30.6001" was
there to avoid errors in representation.  My thanks to:

	steve@taumet.com (Stephen Clamage)
	rh@craycos.com (Robert Herndon)
	ne201ph@prism.gatech.edu (Halvorsen, Peter J.)
	ath@linkoping.telesoft.se (Anders Thulin)
	chl@cs.man.as.uk (Charles Lindsey)
	msb@sq.com (Mark Brader)

fernwood!decwrl!PRC.Unisys.COM!ubbpc!wgh (William G. Hutchison) also
notes that "30.6001" is a signature "that can show if you plagarized
a particular book."  (A good point.)

My special thanks to:

	fisher@sc2a.unige.ch (Markus Fischer) 
		(um, did I copy that address right?)
	msb@sq.com (Mark Brader)

who observed that with the month renumbering, months conform to
the pattern (31, 30, 31, 30, 31), in the relevant range.  Quoting
"msb@sq.com":

	Since the pattern repeats every 5 months, the denominator
	of the rational number has to be 5, and very little
	fiddling is needed after that.

Indeed.  It only took a 2x4 to make me aware of it.  

My thanks to all of you.