わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

ツェラーの公式をCで

f:id:takehikom:20190207125141j:plain

「10月に,Cの授業で打ち込んでもらった,少し長い式を,振り返ることにします.年,月,日の整数値をもとに,曜日を求める,『ツェラーの公式』です.
 下のプログラムコードから先に見ましょう.イコールの左のdowは,曜日に対応する,整数値を格納するための変数で,day of weekの頭文字をとってこの変数名にしました.値は0なら日曜日,1なら月曜日,途中を略して6なら土曜日です.
 右辺に関して,yearが年,monthが月,dayが日,と言いたいところですが,この公式を使う場合には,1月または2月のとき,一つ前の年の13月・14月に置き換えて,使う必要があります.
 このdowへの代入について,もとになっているのは,下向き三角形の上に書いた数式です.wikipedia:ツェラーの公式に書かれている式の一つです。
 この数式を読むにあたり,注意することが2つ,あります.まずは,カギカッコに似ているけれど少し違う記号です.\frac{y}{4}の左右にあるのが一つで,全部で4回,出現します.
 これは『床関数(floor function)』と呼ばれます.中の式を評価して得られる実数値について,その値を超えない最大の整数です.中学・高校で『ガウス記号』という言葉を聞いたことがある人が,もしいれば,大学ではガウス記号は,床関数に取って代わると思ってください.C言語でもこの処理を行う,floorという名前のライブラリ関数があります*1
 プログラムコードに戻ってください.そこでは床関数に対応する記号や,floorを,使用していません.それでもうまくいくのは,変数yearが整数型の場合,year / 4によって,yearを4で割ったときの商となる整数値が得られ,小数部分は切り捨ててくれる*2からです.このように,数式は一見すると複雑だなあと思っても,数式の意味やプログラムコードの意味,すなわち,それぞれが何を表すことになるのかに注意すると,簡略化が図れるのです.
 数式の最後の「mod 7」は,「7で割った余り」です.modはモッドまたはモジュロと読みます.Cでは%という演算子を使って表せます.
 この『%』の演算子は,優先順位が,掛け算の『*』や割り算の『/』と同じです.例えば4+3%2と書いたら,7を2で割った余りではなく,先に3%2を評価して1となり,4+1で5ということです.ですので7で割って余りを求める対象について,カッコとカッコ閉じを書くことになります.ここは数式も同じですね.
 数式ではカッコが1組だけですが,Cのプログラムコードでは,13 * month + 8を5で割った余りを求める際にもカッコを使っているので,2組です.if文の入れ子やforループの入れ子と同じように,カッコと閉じカッコの中に,カッコと閉じカッコがありますので,カッコの入れ子と言って,差し支えありません.
 中学や高校の数学で,中カッコや大カッコを使ってきたかもしれませんが,Cに限らずプログラミングでは,カッコの記号にはそれぞれ意味が定められており,上のコードを『dow = {year + year / 4 - year / 100 + year / 400 + (13 * month + 8) / 5 + day} % 7;』のように書いたらエラーとなります」


関連

*1:ただし,Cのライブラリ関数floorは,引数も戻り値もdouble型です.

*2:yearが負の数のとき,切り捨てとはならないのですが,ツェラーの公式ではグレゴリオ暦を前提としており,紀元前の曜日を求めることは,想定されていません.

*3:本記事は,ガウス記号って数学においてポピュラーではないよなという意識が背景にあります.「はした」に関しては,http://takexikom.hatenadiary.jp/entry/2019/02/07/124449にて見直しを図りました.

*4:べき乗演算子「**」は,昨年度の授業時から利用可能(ブラウザが対応)となっていて,今年度の答案でもよく見かけました.