剰余と切り捨て除算
このレッスンで作るもの — 割り算の答えを整数と余りに分ける
//と%を覚え、飲み会の割り勘を計算します。
剰余と切り捨て除算
第 1 章で扱った割り算 / には、少し困ったところがあります。
print(1000 / 3) # 333.33333333333331000 円を 3 人で割ると 333.3333... 円。お金にこの答えは使えません。実際にほしいのは「1 人 333 円ずつ出して、1 円あまる」という形です。
これを出すのが 切り捨て除算 の // と 剰余 の % です。
/はいつでも小数 (float) を返します。10 / 2ですら5.0です。整数がほしい場面では//を使います。
// は商、% は余り
// は割り算の答えの小数部分を切り捨てて、整数だけを返します。% は割ったときの余りを返します。
print(1000 // 3) # 333
print(1000 % 3) # 1333 × 3 = 999、1000 - 999 = 1 なので、確かに 1 あまります。この 2 つは常にセットで、割られる数 == 商 * 割る数 + 余り の関係が成り立ちます。
print(250 // 4) # 62
print(250 % 4) # 2
print(62 * 4 + 2) # 250 に戻る% は「パーセント」の記号ですが、Python では百分率とは何の関係もありません。読み方は「モジュロ」または「あまり」です。
割り切れるかを調べる
% のいちばん有名な使い道が「割り切れるか」の判定です。余りが 0 なら割り切れています。
print(10 % 2 == 0) # True 偶数
print(7 % 2 == 0) # False 奇数% 2 で偶数と奇数を分ける、% 3 で 3 の倍数を見つける。第 4 章でやる FizzBuzz はこの応用そのものです。
動きを追ってみる
split_bill(1000, 3) の流れを追います。
totalに1000、peopleに3が入るtotal // peopleが333になるtotal % peopleが1になる- その 2 つを f-string に埋め込んで
"1人 333円 あまり 1円"を組み立てる - その文字列を
returnする
第 2 章で覚えた f-string がここで効きます。f"..." の中では {} の中身が計算されて文字列に変わるので、str() で包み直す必要がありません。
def split_bill(total, people):
return f"1人 {total // people}円 あまり {total % people}円"{} の中に total // people のような 式 をそのまま書けるところがポイントです。いったん変数に入れてから埋めても構いません。読みやすいほうを選んでください。
本当は「1 人分」と「あまり」という 2 つの数値をそのまま返したいところです。値を 2 つ同時に返す書き方は第 6 章で扱います。今日は 1 本の文字列にまとめて返します。
負の数での挙動
Python の // は、小数点以下を切り捨てるのではなく 小さいほうへ丸めます。負の数だと直感と違う答えになります。
print(-7 // 2) # -4 (-3.5 より小さい整数)
print(-7 % 2) # 1おこづかい帳では金額が負になることはないので実害はありませんが、「切り捨て」という言葉から -3 を期待すると裏切られる、とだけ覚えておいてください。
よくある間違い
/と//の取り違え —1000 / 3は333.3333333333333という小数です。f"{1000 / 3}円"と書くと、とんでもない見た目になります。整数がほしいときは//です。- 0 で割ってしまう —
10 // 0も10 % 0もZeroDivisionErrorになります。人数のように「0 になりうる値」で割るときは注意が必要です。 %を百分率と思い込む —50 % 100は「50 パーセント」ではなく「50 を 100 で割った余りの 50」です。
エラーの名前は読めば意味が分かるように付いています。
ZeroDivisionErrorは「ゼロで割った」とそのまま書いてあります。焦らず読むのがいちばん速い解決です。
やってみよう
関数 split_bill(total, people) を実装してください。total 円を people 人で割り勘したときの結果を、下記の形の文字列で返します。
1人 333円 あまり 1円1人 のあとに 1 人あたりの金額、円 あまり のあとに余りの金額、最後に 円 です。半角スペースの位置に注意してください。total = 1000、people = 3 なら上のとおり、total = 3000、people = 3 なら 1人 1000円 あまり 0円 になります。割り切れるときも あまり 0円 と表示します。
要件
- 関数名は split_bill で、引数は total と people の2つ
- 1人あたりの金額は // で求める(/ を使うと小数になる)
- 端数は % で求め、割り切れるときも あまり 0円 と表示する
- 戻り値は "1人 333円 あまり 1円" と同じ形の文字列にする
入出力例
split_bill(1000, 3) → "1人 333円 あまり 1円"
split_bill(3000, 3) → "1人 1000円 あまり 0円"
split_bill(250, 4) → "1人 62円 あまり 2円"
split_bill(100, 1) → "1人 100円 あまり 0円"
split_bill(0, 3) → "1人 0円 あまり 0円"
split_bill(5, 10) → "1人 0円 あまり 5円"