うるう年を判定する
うるう年の決め方は「ただし」が 2 回続きます。4 で割り切れる年はうるう年。ただし 100 で割り切れる年は違う。ただし 400 で割り切れる年はやはりうるう年。この 3 段を頭から順に書き下そうとすると、たいてい 2100 年で間違えます。
道具を 1 つずつ確かめてから、ルールの噛み合い方を見ていきます。
割り切れるかどうかは % で聞く
% は割り算の余りを返す演算子です。余りが 0 なら、ちょうど割り切れたということになります。
Java
12 % 5 // 2 割り切れない
20 % 4 // 0 割り切れる
7 % 2 // 1 奇数つまり「x が偶数か」は x % 2 == 0、「偶数ではないか」は x % 2 != 0 と書けます。!= は「等しくない」を聞く比較演算子で、真偽を反転させる ! とは別の記号です。!x % 2 == 0 のように混ぜると、int を真偽値として扱えないと言われて弾かれます。
3 つのルールが、年ごとにどう効くか
3 つの問いに対する答えを年ごとに並べると、どこで結果が分かれるのかが見えます。
| 年 | 4 で割れる | 100 で割れる | 400 で割れる | うるう年 |
|---|---|---|---|---|
| 2024 | はい | いいえ | いいえ | はい |
| 2023 | いいえ | いいえ | いいえ | いいえ |
| 2100 | はい | はい | いいえ | いいえ |
| 2000 | はい | はい | はい | はい |
| 1900 | はい | はい | いいえ | いいえ |
2100 と 2000 を見比べてください。左から 2 列目までは同じで、違うのは 400 の列だけです。ここが正しく効いていれば、残りの年は自然に決まります。逆に、この 2 つが同じ答えになっているなら、3 つ目のルールがどこにも書けていません。
&& と || を混ぜたら、カッコを付ける
&& は || より先に評価されます。書いた本人が思っている区切りとずれても、コンパイルは通ってしまいます。
Java
boolean a1 = x || y && z; // x || (y && z) と読まれる
boolean a2 = (x || y) && z; // 意味が違う&& は左右の両方が true のときだけ true、|| はどちらか一方でも true なら true です。この 2 つを 1 つの式に混ぜるときは、意図した区切りをカッコで書き切ってください。読み手のためというより、半年後の自分のためです。
==を=と打つのも定番の失敗です。year % 4 = 0は「代入しようとしている」と解釈されて止まります。比較はイコール 2 個です。
やってみよう
isLeapYear(int year) を完成させて boolean を返してください。
- 3 つの問いを、それぞれ
%と==!=で 1 つの式として書き下す - 上の表を見ながら、どの組み合わせのときに
trueになるかを決める &&と||でつなぎ、区切りをカッコで示す- 実行して 2024 / 2023 / 2100 / 2000 / 1900 の 5 件を通す
if を並べて書いても構いません。その場合も、上から順に評価されて最初に当たった枝で確定するので、当てはまる年が少ないルールから先に置きます。書き終えたら 2100 と 2000 を頭の中でたどって、答えが分かれることを確かめてから実行してください。
要件
- クラス名は
Solution、メソッド名はisLeapYearにすること - 引数は
int yearの 1 つ、戻り値の型はboolean 4で割り切れる、100で割り切れない、400で割り切れる、の 3 つのルールを正しく組み合わせて判定すること
入出力例
isLeapYear(2024) → true
isLeapYear(2023) → false
isLeapYear(2100) → false
isLeapYear(2000) → true
isLeapYear(1900) → false
isLeapYear(2020) → true