算術 — 割り算、余り、そして小数の罠
7つの算術演算子、どれが先に実行されるか、整数の割り算と余りが役立つ場面、そして小数が時に奇妙な答えを返す理由。
どうやって学びますか?
解決する問題
本が17冊あり、箱には5冊入ります。箱はいくつ必要で、余る本は何冊でしょうか?
答えは17 / 5ではありません。それは3.4になり、3.4箱というものは存在しないからです。答えは2つ必要です: 満杯の箱がいくつかと余りがいくつか。Pythonにはそれぞれのための演算子があり、これらは、これから学ぶ演算子の中でも特に役立つ2つです — ページ分割、秒を時と分に分けること、数が偶数かどうかを調べることは、すべてここから来ます。
もう一つ、初めて目にした人がつまずくことがあります: Pythonでは0.1 + 0.2は0.3になりません。なぜそうならないのか、そしてどう対処すればよいのかも、この章で扱います。
この章を終える頃には
- 7つの算術演算子を使える
- どの計算が先に実行されるか、そしていつ括弧が必要かを説明できる
//と%が適切な道具になる場面を見分けられる- 割り切れる場合でも、
/が必ず小数を返す理由を説明できる - 小数の精度の限界を踏まえた計算を書ける
前提条件: 変数と型.
7つの演算子
print(10 + 3)
print(10 - 3)
print(10 * 3)
print(10 / 3)
print(10 // 3)
print(10 % 3)
print(10 ** 3)13
7
30
3.3333333333333335
3
1
1000最後の3つには補足が必要です:
//— 切り捨て除算。割り算をして整数部分だけを残し、余りは捨てます%— 剰余(余り)。割り算の後に残るもの**— べき乗。10 ** 3は10の3乗です
/は必ず小数を返します。10 / 5でも2ではなく2.0と答えます。割り切れるかどうかで型が変わると、プログラムの振る舞いが予測できなくなります。そのためPythonはここで1つのルールを守っています:/はfloatを意味する。整数が必要なときは//を使います。
箱の問題を解く
books = 17
per_box = 5
full_boxes = books // per_box
left_over = books % per_box
print("Full boxes:", full_boxes)
print("Left over :", left_over)Full boxes: 3
Left over : 23つの箱がいっぱいになり、2冊の本が外に残ります。//と%はペアになっています — 一方は「満杯がいくつか」、もう一方は「余りはいくつか」を答えます。
同じペアは、他の多くの場面にも現れます:
total_seconds = 500
minutes = total_seconds // 60
seconds = total_seconds % 60
print(minutes, "min", seconds, "sec")8 min 20 secそして%は偶数・奇数の判定にも使えます。どんな数も2で割ると、余りは0(偶数)か1(奇数)になります:
print(14 % 2)
print(15 % 2)0
1この余りこそ、後の章の条件分岐(if)の土台になるものです。
計算が先に実行されるもの
Pythonは算数の通常のルールに従います — 掛け算と割り算は、足し算と引き算より先に行われます:
print(10 + 5 * 2)
print((10 + 5) * 2)20
301行目では5 * 2が先に実行され、その後10が足されました。2行目では括弧が順序を変えました。
優先順位が高い順:
***、/、//、%+、-
print(2 + 3 * 4 ** 2)504 ** 2は16、次に3 * 16が48、そして2 + 48が50になります。
迷ったら括弧を使いましょう。 ルールを知っていても、(a + b) / 2と書いたほうがa + b / 2より良いです — 次にそのコードを読む人が、どのルールも思い出す必要がなくなるからです。余分な括弧でコードが遅くなることはなく、意図が明確になるだけです。
これは初心者が最もよくするミスで、平均を求めるときに現れます:
a = 10
b = 20
c = 30
wrong = a + b + c / 3
right = (a + b + c) / 3
print("Wrong:", wrong)
print("Right:", right)Wrong: 40.0
Right: 20.0プログラムはエラーを出しません。赤いエラーも、壊れた箇所もなく — ただ間違った答えが出るだけです。これはバグの中でも最も危険な種類です。 Pythonは警告してくれないからです。算数を自分で確かめることでしか捕まえられません。
小数の罠
print(0.1 + 0.2)0.30000000000000004これはPythonのせいではありません。コンピュータは数を2進数で保存し、0.1は2進数では正確に書けません — ちょうど10進数で1/3が正確に書けず、0.3333...が永遠に続くのと同じです。そのためコンピュータは極めて近い値を保存し、それを2つ足すと、わずかな差が目に見えるようになります。JavaScript、Java、Cも同じように動作します。
実際に影響する点は2つあります:
一つ目 — 表示するときに丸める:
total = 0.1 + 0.2
print(round(total, 2))0.3round(total, 2)は、小数点以下2桁を残す、という意味です。
二つ目 — 2つの小数を==で比べない:
print(0.1 + 0.2 == 0.3)Falseこれは金融計算で誤った答えを生む罠です。本格的なプロジェクトでは、お金をfloatで持つことはしません — 最小単位を整数で保存する(49.99は4999になる)か、別のdecimalモジュールを使います。今は限界がどこにあるかを知っておくだけで十分です。モジュールは後で学びます。
完成例
packing.py:
# Work out packing and shipping for one order
total_items = 47
items_per_box = 6
box_cost = 35.5
full_boxes = total_items // items_per_box
loose_items = total_items % items_per_box
# A partly filled box still costs a full box
boxes_needed = full_boxes
if loose_items > 0:
boxes_needed = full_boxes + 1
shipping = boxes_needed * box_cost
print("Items :", total_items)
print("Full boxes :", full_boxes)
print("Loose items :", loose_items)
print("Boxes needed :", boxes_needed)
print("Shipping :", round(shipping, 2))Items : 47
Full boxes : 7
Loose items : 5
Boxes needed : 8
Shipping : 284.0ifの行はまだ習っていません — それは今後の数章で扱います。今は読むだけで構いません: 箱に入りきらない商品が1つでもあれば、箱があと1つ必要だ、という意味です。
問題が起きたとき
ZeroDivisionError: division by zero 何かを0で割りました。数学でも定義されていないので、Pythonは停止します。割る前に除数を確認しなければなりません — 条件分岐を学べば簡単になります。
10 / 5が2.0になり、2が必要なとき //を使うか、int(10 / 5)と書いてください。前者のほうが良いです: 意図がコードの中で見えるからです。
負の数で//が奇妙な答えを返す -7 // 2は-3ではなく-4です。Pythonは0に向かってではなく、下に丸めます。負の数を扱う場合は覚えておく価値があります。
計算は正しく見えるのに、答えが間違っている 括弧を数え、各ステップを1行ずつに分けて出力してください。ミスはほとんどの場合、演算子の優先順位によるものです。
小数点以下に長く続く桁 それはエラーではなく、小数の振る舞いそのものです。表示するときにround()で短くしてください。
ステップ 4 / 6 — 予想する
理解度をチェック
3行はすべて同じ2つの数に対して、毎回異なる演算子を使っています。出力は何ですか?
print(7 / 2)
print(7 // 2)
print(7 % 2)- A3 3 1
- B3.5 4 1
- C3.5 3.5 1
- D3.5 3 1
プログラムはエラーなく動きますが、平均を40.0と報告します。なぜですか?
a = 10
b = 20
c = 30
average = a + b + c / 3
print("Average:", average)- A`average`はPythonのキーワードなので、値が正しく保存されなかった
- B平均には`//`を使う必要があり、`/`ではない
- C`/`が先に実行されるため、`c`だけが割られた — `(a + b + c) / 3`と書く必要がある
- D3つの数が`int`なので、結果が間違ってしまう
次の2行の出力は何ですか?
print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)- A0.3 True
- B0.3 False
- C0.30000000000000004 False
- D0.30000000000000004 True
回答にはアカウントが必要です
ログインして答えを確認
問題は上にあります。頭の中で答えを考えることがいちばん大切です。ログインすると、正解・解説・3 段階のヒントを確認できます。
やってみよう
time_split.pyという名前のファイルを書いてください。秒数を時・分・秒に分けるプログラムです。
total_seconds = 7385から始めて、出力は次のようになるはずです:
2 h 3 m 5 s3つの条件:
//と%だけを使う — 結果を手で入力しないこと- 3つの値は、それぞれ意味のある名前を付けた別々の変数に入れておく
- 次に
total_secondsを59、60、3600、86399に変えて、それぞれ実行する — 4つすべてが正しく出るか確認する
最後のステップは飛ばさないでください。1つの入力だけで動くプログラムは、本当に動くとは言えません。端の値でも正しく動くプログラムこそが、本当に動くプログラムです。
このミッションにはまだ続きがあります
上で読んだ内容がミッションのすべてで、削られた部分はありません。Pro では次の内容が追加されます:
- 内部で実際に何が起きているか — Python がこれをどう実行するのか
- 演習の完全な解答と、ステップごとの解説
- さらに難しい追加演習
- このテーマでよく聞かれる面接の質問と模範解答