うるう年はなぜ複雑なのか視覚的に実感する

## うるう年とは
- 1年が366日ある年
- 西暦が4の倍数であり，100の倍数ではない年がうるう年
    - ただし，400の倍数である年はうるう年
- 4, 8, 12, ..., 96, 104, ..., 196, 204, ..., 296, 304, ..., 396年はうるう年
- 100, 200, 300年はうるう年ではない
- 400年はうるう年

:::note info
ややこしすぎる...！
:::

## うるう年の原理
- 地球の公転と1年の日数とのずれ
    - 地球の公転：365.24218944日（[Wikipedia - 年](https://ja.wikipedia.org/wiki/%E5%B9%B4)，閲覧時の最新更新日時：2024/05/16(木)22:27 ）
    - 1年の日数：365日

上記のずれが蓄積して，うるう年が発生する

## うるう年がなかった場合のずれを計算する
- 日数のずれをプロットするコードを示す
```python
import matplotlib.pyplot as plt

revolution = 365.24218944
y = 365

loss = [(revolution-y)*i for i in range(2024)]
m3 = [365/4 for i in range(2024)]
m6 = [365*2/4 for i in range(2024)]
m9 = [365*3/4 for i in range(2024)]
m12 = [365 for i in range(2024)]
t = [i for i in range(2024)]
plt.plot(t, loss)
plt.plot(t, m3, color='red')
plt.plot(t, m6, color='red')
plt.plot(t, m9, color='red')
plt.plot(t, m12, color='red')
plt.savefig("loss_day.png")
```
- 実行結果

    ![loss_day.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768359/4c705916-1c6d-9a17-6e0b-0e36b166e49a.png)

四季が存在するとした場合に，計算上で実際よりも季節が1つ，2つ，3つ，4つ進んでしまうところを赤い直線で示した
- 300-400年あたりで季節1つ分ずれている
- 750-800年あたりで季節2つ分ずれている
    - カレンダー上で夏でも実際は冬なので，夏なのに最高気温10℃といった現象が起きる
- 1500-1600年あたりでついに1年分ずれている

:::note info
1年単位では小さな誤差でも，数百年たつと季節が変わるまでの誤差になる
:::

## うるう年の調整を実装
- 計算上で実際よりも1年で$0.24218944 \risingdotseq \frac{1}{4}$日進む
    - 4年で1日分進む
    - 4年に1度だけ，1日分カレンダーを遅らせればよい
```python
import matplotlib.pyplot as plt

revolution = 365.24218944
y = 365

loss = [0]
for i in range(1,2024):
  if i % 4 == 0:
    loss.append(loss[-1]+revolution-y-1)
  else:
    loss.append(loss[-1]+revolution-y)
t = [i for i in range(2024)]
m1 = [-1 for i in range(2024)]
plt.plot(t[:250], loss[:250])
plt.plot(t[:250], m1[:250], 'red')
plt.savefig("loss_day_simpleleap.png")
```
- 見やすいように前半250年のみ切り出した実行結果

    ![loss_day_simpleleap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768359/bb95ebd6-d042-bba0-427d-8399f21a344f.png)
    <br>
- 今度は100-150年あたりで1日今度はカレンダーが遅れる
:::note info
新たに生じる微妙なずれも修正したい
:::

## 100年に1回はうるう年とはしない調整を実装
```python
import matplotlib.pyplot as plt

revolution = 365.24218944
y = 365

loss = [0]
for i in range(1,2024):
  if i % 4 == 0 and i % 100 != 0:
    loss.append(loss[-1]+revolution-y-1)
  else:
    loss.append(loss[-1]+revolution-y)
t = [i for i in range(2024)]
m1 = [1 for i in range(2024)]
plt.plot(t[:500], loss[:500])
plt.plot(t[:500], m1[:500], 'red')
plt.savefig("loss_day_100notleap.png")
```
- 見やすさのために前半500年部分のみ切り出した実行結果

    ![loss_day_100notleap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768359/f0b76bba-98f2-3ceb-9689-b73c33c6a2bd.png)
    <br>
- 今度は300-500年あたりで1日カレンダーが進む
:::note info
このずれを400年に一度うるう年をいれることで調整
:::

## 400年に1回はうるう年とする調整を実装
```python
import matplotlib.pyplot as plt

revolution = 365.24218944
y = 365
now = 10000
loss = [0]
for i in range(1,now):
  if i % 4 == 0 and (i % 100 != 0 or i % 400 == 0):
    loss.append(loss[-1]+revolution-y-1)
  else:
    loss.append(loss[-1]+revolution-y)
t = [i for i in range(now)]
m1 = [-1 for i in range(now)]
plt.plot(t, loss)
plt.plot(t, m1, 'red')
plt.savefig("loss_day_400leap.png")
```

- 誤差を見るために前半5000年まで切り出した実行結果

    ![loss_day_400leap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768359/3071f9e2-40d7-77c1-9a60-1c8276313621.png)
    <br>

- 2000年くらいまではほぼ誤差ないが3200年くらいでカレンダーが1日遅れる

## 3200年に1回はうるう年でない年をつくる
```python
import matplotlib.pyplot as plt

revolution = 365.24218944
y = 365
now = 200000
loss = [0]
for i in range(1,now):
  if i % 3200 == 0:
      loss.append(loss[-1]+revolution-y)
  elif i % 400 == 0:
      loss.append(loss[-1]+revolution-y-1)
  elif i % 100 == 0:
      loss.append(loss[-1]+revolution-y)
  elif i % 4 == 0:
      loss.append(loss[-1]+revolution-y-1)
  else:
      loss.append(loss[-1]+revolution-y)
t = [i for i in range(now)]
m1 = [0 for i in range(now)]
plt.plot(t, loss)
plt.plot(t, m1, 'red')
plt.savefig("loss_day_3200notleap.png")
```
- 200000年分切り出した実行結果

    ![loss_day_4000notleap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768359/27abd5dc-b9c3-ea89-7ccd-12ffac205814.png)

:::note info
しばらくは安泰そう
:::

## 1000000年までプロットしてみる
![loss_day_3200notleap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768359/e0e8d587-f399-caa2-f8dd-ce0d5b588820.png)
- 500000 - 600000年あたりで1日ずれている
- 今まで，$2^m \times 10^n$年ごとに調整してきた
- よって，範囲内で該当する$512000 = 2^9 \times 10^3$年で調整すればうまくいきそう
## 512000年に1回はうるう年を入れる
```python
import matplotlib.pyplot as plt

revolution = 365.24218944
y = 365
now = 50000000
loss = [0]
for i in range(1,now):
  if i % 512000 == 0:
      loss.append(loss[-1]+revolution-y-1)
  elif i % 3200 == 0:
      loss.append(loss[-1]+revolution-y)
  elif i % 400 == 0:
      loss.append(loss[-1]+revolution-y-1)
  elif i % 100 == 0:
      loss.append(loss[-1]+revolution-y)
  elif i % 4 == 0:
      loss.append(loss[-1]+revolution-y-1)
  else:
      loss.append(loss[-1]+revolution-y)
t = [i for i in range(now)]
m1 = [0 for i in range(now)]
plt.plot(t, loss)
plt.plot(t, m1, 'red')
plt.savefig("loss_day_512000leap.png")
```
- 実行結果

    ![loss_day_12800leap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768359/b34a1439-6f6b-059f-dd68-f5776cd7ce55.png)

:::note info
5000万年後くらいまではこの調整で通りそう
:::