2015年3月2日月曜日

HP-16Cのプログラム技法

私の個人用電卓で他の電卓に見当たらない便利な機能はユリウス日の計算である.

-4712年1月1日を0とした通日である. 例えば2015年3月2日は20150302と入力し, JDのキーを押すと2457084が得られる. これに1を足し7で割った剰余を計算すると1になり月曜であるのが分る.

これをHP-16Cのプログラムにしたいが, グレゴリオ改暦の前を使うことはまずないので(-4712年1月1日が0になるか確認するくらいだ), 今回はFixed Day Numberを計算することにした.

Fixed Day Number(RD, Rata Die)は改暦よりも前までグレゴリオ暦が使われていたとした, 1年1月1日 (月曜)を1にするものである. 2015年3月2日RDは735659である. ユリウス日より1721425日少ない.

Calendrical Calculationのアルゴリズムは次のようだ(同書ではCommon Lispを使う)
(defun fixed-from-gregorian(year month day)
(+ (* 365 (1- year))
   (quotient (1- year) 4)
   (- (quotient (1- year) 100))
   (quotient (1- year) 400)
   (quotient (- (* 367 month) 362) 12)
   (if (<= month 2) 0
    (if (gregorian-leap-year? year) -1 -2))
   day))
要するに年数に365を掛け, 閏年の調整をし, 月始めまでの日数を求め, 日付を足す. HP-16Cのプログラムはこうだ.
001 43.22.b  LBL B ;20150302 GSB B
002 44.00    STO 0 ;ymd -> 0
003 43.05.00 CF 0  ;flag 0 閏年
004 43.05.01 CF 1  ;flag 1 m<=2
005 04       4
006 00       0
007 00       0
008 44.04    STO 4 ;400->4
009 42.b     SR
010 42.b     SR
011 44.03    STO 3 ;100->3
012 42.09    RMD   ;ymd%100
013 44.02    STO 2 ;d -> 2
014 02       2     ;m<=2の比較用
015 45.00    RCL 0 ;ymd
016 45.03    RCL 3 ;100
017 10       /
018 44.00    STO 0 ;ym
019 45.03    RCL 3 ;100
020 42.09    RMD   ;ym%100
021 44.01    STO 1 ;m -> 1
022 43.01    x<=y
023 43.04.01 SF 1  ;m<=2ならF1をセット
024 45.00    RCL 0 ;ym
025 45.03    RCL 3 ;100
026 10       /
027 44.00    STO 0 ;y -> 0
028 45.03    RCL 3
029 42.09    RMD
030 43.40    x=0   ;y%100=0?
031 22.00    GTO 0
032 45.00    RCL 0 ;y
033 04       4     ;4
034 22.01    GTO 1
035 43.22.00 LBL 0
036 45.00    RCL 0 ;y
037 45.04    RCL 4 ;400
038 43.22.01 LBL 1
039 42.09    RMD
040 43.30    x=0
041 43.04.00 SF 0 ;y%(4or400)=0
042 03       3
043 06       6
044 07       7
045 44.05    STO 5 ;367 -> 5
046 05       5
047 30       -
048 44.06    STO 6 ;362 -> 6
049 03       3
050 40       +     ;365
051 45.00    RCL 0 ;y
052 01       1
053 30       -     ;-1
054 44.00    STO 0 ;y-1 -> 0
055 20       *     ;365*(y-1)
056 45.00    RCL 0
057 04       4
058 10       /
059 40       +     ;+(y-1)/4
060 45.00    RCL 0
061 45.03    RCL 3
062 10       /
063 30       -     ;-(y-1)/100
064 45.00    RCL 0
065 45.04    RCL 4
066 10       /
067 40       +     ;+(y-1)/400
068 45.01    RCL 1 
069 45.05    RCL 5
070 20       *     ;m*367
071 45.06    RCL 6
072 30       -     ;-362
073 01       1
074 02       2
075 10       /     ;/12
076 40       +
077 45.02    RCL 2
078 40       +     ; +day
079 43.06.01 F? 1
080 43.21    RTN   ;m<=2なら帰る
081 02       2     ;平年なら2
082 43.06.01 F? 0
083 42.b     SR    ;閏年なら1
084 30       -     ;引く
085 43.21    RTN   ;帰る
テストはクリティカルな日付で行う

20150228 => 735657
20150301 => 735658

20120229 => 734562
20120301 => 734563

20141231 => 735598
20150101 => 735599

00010101 => 1

RDは7での剰余がそのまま曜日になる(1年1月1日月曜を1にしたから.)

0 件のコメント: