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.