コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2009年11月18日 >>> 2009年11月18日
link もっと後

2009年11月18日

経過日を年月日に変換 - その2

前回(2009年11月16日の日記参照)は経過日から月日への計算を行いました。残るは年の計算です。

グレゴリオ歴の周期性

前回も紹介したとおり、グレゴリオ暦の平年、閏年には下記の法則があります。

  1. 平年は365日、閏年は366日
  2. 西暦が4で割り切れる年は閏年(1年が366日)
  3. 西暦が100で割り切れる年は平年(1年が365日)
  4. 西暦が400で割り切れる年は閏年(1年が366日)

4年周期は平年、平年、平年、閏年のパターンです。

100年周期は4年周期を25回繰り返すだけですが、最後の100年目だけは閏年ではありません。

400年周期は100年周期を4回繰り返すだけですが、最後の400年目だけは閏年になります。400年以上を扱うルールはありませんので、以降400年周期で同じパターンが続きます。

図示すると下記のようになります。オレンジの四角が閏年を表しています。


閏年のパターン

各周期の日数の計算式は下記の通りです。

  1. 1年は365日
  2. 4で割り切れるときは閏年、つまり最後の年だけ +1日
    365+365+365+366
    =365*4+1
    =1461
  3. 100で割り切れるときは平年 、つまり最後の年だけ -1日
    1461+1461+…++1461+1460
    =1461*25-1
    =36524
  4. 400で割り切れるときは閏年 、つまり最後の年だけ +1日
    36524+36524+36524+36525
    =36524*4+1
    =146097

パターンがわかってしまえば、与えられた経過日にこのパターンがいくつ含まれているか?を計算するのみです。

経過日から年への変換

では実際に経過日から年を計算してみます。しつこいですがパターンは下記4つです。経過日にこれらのパターンがいくつ含まれているか調べます。

  • パターンA: 400年 = 146097日
  • パターンB: 100年 = 36524日
  • パターンC: 4年 = 1461日
  • パターンD: 1年 = 365日

なぜ上記パターンの数を求めれば年数が出るのか?がわかる人は次の章を飛ばして読んでください。

桁の話

ここでは桁の概念についてと、年への換算にどう使うか?を補足させていただきます。

私たちにおなじみの10進数は1234のように書きますが、これってどういう意味でしょうか?

10進数の1桁目は10^0がいくつ含まれているか、2桁目は10^1がいくつ含まれているかを示します。n桁目は10^(n-1) がいくつ含まれているか?を示します。

ですから10進数で1234は(1 * 10^3 + 2 * 10^2 + 3 * 10^1 + 4 * 10^0 = 1234)という数(10進数表記)を表します。

当たり前?でもこれは m進数でも同様で、n桁目はm^(n-1) がいくつ含まれているか?を示します。

ですから8進数の1234は(1 * 8^3 + 2 * 8^2 + 3 * 8^1 + 4 * 8^0 = 668)という数(10進数表記)を表します。

経過日から年を求める場合も、これと似た考え方ができます。各パターンの数を桁と見なして(400年の桁、100年の桁、4年の桁、1年の桁)、10進数へと換算してやればよいのです。

各パターンの数(400年、100年、4年、1年)が1, 2, 3, 3であれば(1 * 400 + 2 * 100 + 3 * 4 + 3 * 1 = 615)という年(10進数表記)を表します。

このように各パターンの数を求めてあげることで、年数が計算可能なのです。

経過日から年への計算式

パターンAの数は(経過日 / 146097)です。余りの経過日は400年未満のどこか(0年3月1日〜399年2月29日)を表します。これはパターンBの計算に回します。

パターンBの数は(経過日 / 36524)です。余りの経過日は100年未満のどこか(0年3月1日〜99年2月28日)を表します。余りは同様にパターンCの計算に回します。

しかし146096日(399年2月29日)の場合に3となるべきところが4になり間違えてしまうため、特別に3とします。その際の余り経過日は99年2月29日ですから36525 - 1 = 36524日(開始が0日のため1引く)となります。

パターンCの数は(経過日 / 1461)です。余りの経過日は4年未満のどこか(0年3月1日〜3年2月29日)を表します。余りは同様にパターンDの計算に回します。

パターンDの数は(経過日 / 365)です。余りの経過日は1年未満のどこか(0年3月1日〜0年2月28日)を表します。ここの余りは経過日から月日を求める計算に回します。

しかし1460日(3年2月29日)の場合に3となるべきところが4になり間違えてしまうため、特別に3とします。その際の余り経過日は0年2月29日ですから366 - 1 = 365日(開始が0日のため1引く)となります。

実装例

実装する関数の仕様は下記の通りです。

date
400で割り切れる西暦(1600年、2000年など)の3月1日からの経過日を渡します。値域は正の整数です。
year
年を返します。値域は正の整数です。
mod
1年に満たない経過日を返します。値域は0〜365です。
返り値
成功ならば0を返します。エラーが起きた場合は -1を返します。

この処理をC言語で書くと下記のようになります。

経過日から年への変換、実装例

int date_to_year(int date, int *year, int *mod)
{
        int a400, a100, a4, a;
        int m400, m100, m4, m;

        if (date < 0) {
                return -1;
        }

        a400 = date / 146097;
        m400 = date % 146097;
        if (m400 == 146096) {
                a100 = 3;
                m100 = 36524;
        } else {
                a100 = m400 / 36524;
                m100 = m400 % 36524;
        }
        a4 = m100 / 1461;
        m4 = m100 % 1461;
        if (m4 == 1460) {
                a = 3;
                m = 365;
        } else {
                a = m4 / 365;
                m = m4 % 365;
        }

        if (year) {
                *year = a400 * 400 + a100 * 100 + a4 * 4 + a;
        }
        if (mod) {
                *mod = m;
        }

        return 0;
}

これで経過日から年への変換は完成ですが、まだテストが終わっていません。

月日の変換のときは、入力に対する答えがたかだか366通りと少なかったため、目でチェックしました。しかし今回は400年つまり146097日もの数をチェックしなければなりません。こんな数を目で一々チェックしていたら頭がおかしくなります。

テストの方法についてはまた次回に。

編集者:すずき(2009/11/23 02:32)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2009年11月18日 >>> 2009年11月18日
link もっと後

管理用メニュー

link 記事を新規作成

<2009>
<<<11>>>
1234567
891011121314
15161718192021
22232425262728
2930-----

最近のコメント5件

  • link 24年4月22日
    hdkさん (04/24 08:36)
    「うちのHHFZ4310は15年突破しまし...」
  • link 24年4月22日
    すずきさん (04/24 00:37)
    「ちゃんと数えてないですけど蛍光管が10年...」
  • link 24年4月22日
    hdkさん (04/23 20:52)
    「おお... うちのHHFZ4310より後...」
  • link 20年6月19日
    すずきさん (04/06 22:54)
    「ディレクトリを予め作成しておけば良いです...」
  • link 20年6月19日
    斎藤さん (04/06 16:25)
    「「Preferencesというメニューか...」

最近の記事20件

  • link 24年2月7日
    すずき (04/24 02:52)
    「[複数の音声ファイルのラウドネスを統一したい] PCやデジタル音楽プレーヤーで音楽を聞いていると、曲によって音量の大小が激しく...」
  • link 24年4月22日
    すずき (04/23 20:13)
    「[仕事部屋の照明が壊れた] いきなり仕事部屋のシーリングライトが消えました。蛍光管の寿命にしては去年(2022年10月19日の...」
  • link 24年4月17日
    すずき (04/18 22:44)
    「[VSCodeとMarkdownとPlantUMLのローカルサーバー] 目次: LinuxVSCodeのPlantUML Ex...」
  • link 23年4月10日
    すずき (04/18 22:30)
    「[Linux - まとめリンク] 目次: Linuxカーネル、ドライバ関連。Linuxのstruct pageって何?Linu...」
  • link 20年2月22日
    すずき (04/17 02:22)
    「[Zephyr - まとめリンク] 目次: Zephyr導入、ブート周りHello! Zephyr OS!!Hello! Ze...」
  • link 24年4月16日
    すずき (04/17 02:05)
    「[Zephyr SDKのhosttoolsは移動してはいけない、その2 - インストール時のバイナリ書き換え] 目次: Zep...」
  • link 24年4月15日
    すずき (04/17 01:47)
    「[Zephyr SDKのhosttoolsは移動してはいけない、その1 - 移動させると動かなくなる] 目次: ZephyrZ...」
  • link 24年4月11日
    すずき (04/17 00:37)
    「[VScodeとAsciiDocとKrokiローカルサーバー] 目次: LinuxAsciiDoc ExtensionはAsc...」
  • link 24年4月12日
    すずき (04/16 00:12)
    「[台湾東部沖地震に寄付] ささやかではありますが台湾東部沖地震に寄付しました。日本の赤十字社→台湾の赤十字(正式名称...」
  • link 22年9月3日
    すずき (04/16 00:08)
    「[MarkDownのその向こう] 目次: Linux簡単なドキュメントやメモはMarkDownで書くことが多いですが、気合を入...」
  • link 22年9月4日
    すずき (04/16 00:08)
    「[Asciidocをさらに活用] 目次: Linux前回(2022年9月3日の日記参照)、Asciidocのプレビュー環境の設...」
  • link 24年3月19日
    すずき (04/16 00:07)
    「[モジュラージャックの規格] 目次: Arduino古くは電話線で、今だとEthernetで良く見かけるモジュラージャックとい...」
  • link 23年6月2日
    すずき (04/16 00:07)
    「[Arduino - まとめリンク] 目次: Arduino一覧が欲しくなったので作りました。 M5Stackとesp32とA...」
  • link 24年4月9日
    すずき (04/12 12:44)
    「[初めて作ったボード動作せず(手で直した)] 目次: Arduino以前(2024年3月24日の日記参照)発注して、全く動ない...」
  • link 24年4月2日
    すずき (04/12 11:00)
    「[KiCadが動かなくなったのでビルド] 目次: ArduinoDebian Testingなマシンをapt-get upgr...」
  • link 24年4月3日
    すずき (04/12 11:00)
    「[初めて作ったボード動作せず(燃えた)] 目次: Arduino以前(2024年3月24日の日記参照)発注したPCBが届いたの...」
  • link 24年3月24日
    すずき (04/12 11:00)
    「[PCBを設計して注文] 目次: Arduinoシューティングの練習でいつもお世話になっているTARGET-1秋葉原店に、6つ...」
  • link 24年3月25日
    すずき (03/26 03:20)
    「[Might and Magic Book One TASのその後] 目次: Might and Magicファミコン版以前(...」
  • link 21年10月4日
    すずき (03/26 03:14)
    「[Might and Magicファミコン版 - まとめリンク] 目次: Might and Magicファミコン版TASに挑...」
  • link 24年3月18日
    すずき (03/19 11:47)
    「[画面のブランクを無効にする] 目次: LinuxROCK 3 model CのDebian bullseyeイメージは10分...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 04/24 08:36