Python の演算子:算術演算、// と %、比較、and/or/not、python round の使い方
Python の / は常に float を返し、// は小数点以下を切り捨てた整数部分、% は余り、** はべき乗です。round(x, n) は n 桁に丸めます(銀行家の丸め:round(2.5) は 2、round(3.5) は 4)。切り上げと切り下げには math.ceil と math.floor を、絶対値には abs を使います。
Python の演算子は、値から新しい値を作る記号です。+ は足し算、// は割り算の整数部分、and は条件の結合を表します。この記事では、Python 演算子の一覧と例、/ と // の違い、and、or、not の論理、そして python round、math.ceil、math.floor、abs といった丸めの関数を解説します。紹介する例はすべて REPL に貼り付けて確かめられます。
Python 演算子の一覧
演算子は用途ごとにグループに分かれます。全部を暗記する必要はありません。実際のコードでよく使われるのは、算術演算、比較、論理の組み合わせです。
| グループ | 演算子 | 例 |
|---|---|---|
| 算術 | + - * / // % ** | 7 // 2 → 3 |
| 比較 | == != < > <= >= | 3 < 5 → True |
| 論理 | and or not | not True → False |
| 同一性 | is、is not | x is None |
| 所属 | in、not in | "コ" in "コーヒー" → True |
| 代入 | = += -= *= /= //= %= **= | total += 250 |
| セイウチ | := | if (n := len(s)) > 10: |
| ビット演算 | & | ^ ~ << >> | 5 & 3 → 1 |
算術演算子
足し算、引き算、掛け算は、学校で習ったとおりに動きます。式に一つでも float が含まれていれば、結果も float になります。2 + 1.0 は 3.0 です。Python の整数はオーバーフローしません。2 ** 100 も桁数に関係なく正確に計算されます。
>>> 250 + 120
370
>>> 12.5 * 3
37.5
>>> 2 ** 10
1024
>>> 2 ** 0.5
1.4142135623730951
べき乗 ** 演算子
べき乗はアスタリスクを二つ書きます。Python の ^ はべき乗ではなく、ビット単位の排他的論理和です。そのため 2 ^ 3 は 8 ではなく 1 を返します。小数の指数は平方根などになります。9 ** 0.5 は 3.0 です。関数 pow(x, y) も同じ計算をします。3 番目の引数を渡すと剰余を求められます。pow(2, 10, 1000) は 24 を返します。
優先順位にも注意してください。** は単項マイナスより先に計算されるため、-2 ** 2 は -4 になります。負の数を二乗したい場合は、括弧を使って (-2) ** 2 と書きます。
割り算:/、// と %
Python には二種類の割り算があり、初心者が驚く原因になりがちです。通常の割り算 / は、割り切れる場合でも常に float を返します。整数の割り算 // は小数部分を切り捨てます。% は余りを返します。
>>> 7 / 2
3.5
>>> 8 / 2
4.0
>>> 7 // 2
3
>>> 7 % 2
1
整数の割り算 // と余り %:実例
// と % の組み合わせは、「整数で何回あり、何が余るか」を求める問題に使えます。講座の家計簿プログラムでは、正確さを保つために金額を円ではなく最小単位(ここでは 100 分の 1 円の単位)で保存し、それを円と端数に分けています。
sen = 125050 # 金額を最小単位で保存
yen = sen // 100 # 1250 — 整数の円
rest = sen % 100 # 50 — 端数
print(yen, rest) # 1250 50
print(40 // 7, "週と", 40 % 7, "日") # 5 週と 5 日
組み込み関数 divmod を使うと、両方の結果をまとめて得られます。divmod(125050, 100) は (1250, 50) のタプルを返します。余りは偶数判定にも使えます。n % 2 == 0 は、n が偶数のとき真になります。
負の数と //:切り捨ては負の方向へ
演算子 // は単に小数部分を捨てるのではなく、負の無限大の方向へ切り捨てます。正の数では違いはありませんが、負の数では結果が変わります。Python では、余り % の符号は除数と同じになり、常に a == (a // b) * b + a % b が成り立ちます。
>>> -7 // 2
-4
>>> -7 % 2
1
>>> int(-7 / 2) # 小数部分を捨てる(0 の方向へ)
-3
ゼロ除算:どんなエラーになるか
三つの演算子のどれでもゼロで割ると、ZeroDivisionError が発生します。整数でも小数でも同じです。try/except で捕まえるか、除数が 0 でないか事前に確認します。
>>> 10 / 0
Traceback (most recent call last):
...
ZeroDivisionError: division by zero
>>> count = 0
>>> avg = 1500 / count if count else 0
>>> avg
0
比較演算子
比較の結果は True か False です。等しいかどうかは == で判定します。一つの = は代入です。文字列は文字コードの順に比較されるため、"B" < "a" は真になります。大文字は小文字より前にあるからです。
>>> 250 == 250.0
True
>>> 3 != 4
True
>>> 1 < 5 <= 10 # 連鎖比較: 1 < 5 and 5 <= 10
True
>>> 0.1 + 0.2 == 0.3
False
連鎖比較(0 <= x < 100 など)は Python の便利な特徴で、and を書く必要がありません。最後の例は小数の誤差に注意するためのものです。0.1 + 0.2 は 0.30000000000000004 になります。小数同士の比較には math.isclose(a, b) を使い、お金は最小単位の整数か Decimal で保存してください。
論理演算子 and、or、not
Python の論理演算子は、他の言語の && や || ではなく、英単語で書きます。and は両方が真のときに真、or は少なくとも一方が真のときに真、not は真偽を反転します。
| a | b | a and b | a or b | not a |
|---|---|---|---|---|
| True | True | True | True | False |
| True | False | False | True | False |
| False | True | False | True | True |
| False | False | False | False | True |
優先順位は、not、and、or の順です。True or False and False は True になります。and が先に計算されるからです。複雑な条件では括弧を付けましょう。読む人にとってわかりやすくなります。
and と or が返す値
and と or は、必ずしも True や False を返すわけではありません。どちらかのオペランドの値を返します。or は最初の真の値(真がなければ最後の値)を返し、and は最初の偽の値(偽がなければ最後の値)を返します。偽とみなされるのは、0、0.0、空文字列、空のコレクション、None、False です。
>>> name = ""
>>> name or "ゲスト"
'ゲスト'
>>> 5 and 0
0
>>> not ""
True
評価は遅延して行われます。左側の結果だけで答えが決まる場合、右側は評価されません。そのため count and total / count は、count == 0 のときにゼロ除算でエラーになりません。not は、ほかの二つと違って、常に bool を返します。
is と in 演算子
== は値を比べ、is は二つの名前が同じオブジェクトを指しているかを確かめます。空のカートが二つあれば、値は等しくても、それは同じオブジェクトではありません。is が必ず必要になるのは、None の判定です。if x is None と書きます。
>>> a = [250, 120]
>>> b = [250, 120]
>>> a == b, a is b
(True, False)
>>> c = a
>>> c is a
True
数値や文字列を is で比べてはいけません。内部のキャッシュのおかげで「たまたま動く」ことがありますが、結果は実装に依存します。Python は x is 5 のような書き方に対して SyntaxWarning を出します。
in 演算子は所属を判定します。文字列の中の部分文字列、リストの要素、辞書のキーを調べられます。not in はその逆です。
>>> "コーヒー" in "コーヒーを飲みました"
True
>>> "食費" in {"食費": 450, "交通費": 300}
True
>>> 5 not in [1, 2, 3]
True
代入演算子とセイウチ演算子 :=
+=、-=、*=、//= などの複合代入は省略形です。total += 250 は total = total + 250 と同じ意味です。Python には ++ や -- がありません。x++ と書くと構文エラーになります。
セイウチ演算子 := は、式の途中で値を代入します。名前の由来は、セイウチの目と牙に似ているからです。値を調べると同時に、その値をあとで使いたいときに役立ちます。
items = ["コーヒー", "タクシー", "昼食", "映画"]
if (n := len(items)) > 3:
print(f"出費が多すぎます: {n} 件")
while (line := input("金額: ")) != "":
print(int(line) * 2)
セイウチ演算子がなければ、len を二回呼ぶか、代入を別の行に書く必要があります。ただし、頻繁に使うと読みにくくなります。行の意味がわかりにくくなったら、通常の代入に戻しましょう。
丸め:round、ceil、floor
Python の丸めには、組み込み関数 round と、math モジュールの関数があります。それぞれ役割が違い、混同しやすい点です。
| 関数 | 動作 | 2.5 | -2.5 | 2.7 |
|---|---|---|---|---|
round(x) | 最も近い整数。ちょうど中間は偶数へ | 2 | -2 | 3 |
math.floor(x) | 負の無限大の方向へ切り下げ | 2 | -3 | 2 |
math.ceil(x) | 正の無限大の方向へ切り上げ | 3 | -2 | 3 |
math.trunc(x)、int(x) | 小数部分を捨てる(0 の方向へ) | 2 | -2 | 2 |
round 関数と銀行家の丸め
関数 round(x, n) は小数点以下 n 桁に丸めます。第二引数を省くと int を返します。注意点は、Python の round が「銀行家の丸め」を使うことです。中間の値は最も近い偶数に丸められます。そのため round(2.5) は 2、round(3.5) は 4 になります。大量の計算で誤差が一方向に偏らないようにするための仕組みです。
>>> round(2.5), round(3.5)
(2, 4)
>>> round(3.14159, 2)
3.14
>>> round(1250, -2) # 百の位へ
1200
>>> round(2.675, 2) # 2.68 ではなく 2.67。2 進数では 2.67499... だから
2.67
学校で習う「中間は切り上げ」の丸め、たとえばレシートの計算をしたいときは、Decimal と ROUND_HALF_UP モードを使います。浮動小数点の誤差を引き継がないように、数値は文字列で渡しましょう。
>>> from decimal import Decimal, ROUND_HALF_UP
>>> Decimal("2.5").quantize(Decimal("1"), ROUND_HALF_UP)
Decimal('3')
>>> Decimal("2.675").quantize(Decimal("0.01"), ROUND_HALF_UP)
Decimal('2.68')
講座のルールとして、丸めは表示するときだけ行いましょう。表示を整えるだけなら round は不要です。f 文字列の f"{amount:.2f}" で小数 2 桁を表示でき、値自体は正確なままです。
math.ceil と math.floor:切り上げと切り下げ
math.ceil は「足りない」ことが許されないときに使います。たとえば、何台のバスを手配すればよいかを求める場合です。math.floor は、完全な単位だけを数えたいときに使います。どちらの関数も int を返します。
import math
guests = 47
seats = 20
print(math.ceil(guests / seats)) # バス 3 台
print(math.floor(9.99)) # 9
print(-(-guests // seats)) # 3 — math を使わず // で切り上げ
math モジュールには、ほかにも math.sqrt(平方根)、math.isclose(小数の比較)、math.pi、math.gcd などがあります。Python 3.15 では、整数の数学を扱うサブモジュール math.integer(PEP 791)が加わりました。comb、factorial、gcd、isqrt、lcm、perm が含まれ、従来の math.gcd なども引き続き使えます。
abs 関数:絶対値
abs(x) は絶対値、つまり符号を除いた値を返します。組み込み関数なので、インポートは不要です。整数、小数、複素数に使えます。たとえば 3+4j に対しては、ベクトルの長さ 5.0 を返します。
>>> abs(-250)
250
>>> abs(-12.5)
12.5
>>> budget, spent = 5000, 5320
>>> abs(budget - spent) # どれだけ予算からずれたか
320
典型的な使い方は、方向を無視した差の計算や、許容誤差との比較です。abs(a - b) < 0.001 のように書きます。小数の比較には、数値の大きさも考慮する math.isclose の方が確実です。
演算子の優先順位
一つの式に複数の演算子があるとき、Python は優先順位の高いものから順に計算します。
**- 単項演算子
-x、+x、~x * / // %+ -- ビットシフトとビット演算
- 比較、
in、is notandor:=
たとえば 2 + 3 * 4 は 14、(2 + 3) * 4 は 20 です。迷ったら括弧を付けましょう。余分な括弧にコストはありませんが、優先順位のミスは見つけるのに時間がかかります。
演算子でよくある間違い
| 間違い | 起こること | 正しい書き方 |
|---|---|---|
if x = 5: | SyntaxError: 代入になっている | if x == 5: |
べき乗の代わりに 2 ^ 3 | ビット単位の XOR になり、結果は 1 | 2 ** 3 |
8 / 2 で整数を期待する | 4.0 が返る | 8 // 2 |
x == 1 or 2 | 常に真。or 2 が評価されるため | x in (1, 2) |
round(2.5) で 3 を期待する | 銀行家の丸めで 2 になる | Decimal と ROUND_HALF_UP |
"5" + 5 | TypeError | int("5") + 5 |
まとめ
覚えておきたいのは次の点です。/ は常に float を返し、// は負の方向へ切り捨て、% は除数と同じ符号の余りを返します。べき乗は ** です。論理演算子 and、or、not は英単語で書き、遅延評価されます。is は None の判定に使います。python round は偶数方向へ丸め、切り上げと切り下げには math.ceil と math.floor、絶対値には abs を使います。講座では、これらの演算子を家計簿プログラムの中で実際に使いながら学びます。お金を最小単位で管理する例もそこで扱います。
よくある質問
小数点以下 2 桁に丸めるにはどうしますか?
round(x, 2) を使います。表示だけを整えたい場合は、値を変えない f 文字列 f"{x:.2f}" が適しています。
Python で round(0.5) が 0 を返すのはなぜですか?
round は中間の値を最も近い偶数に丸めるためです。0 は偶数なので 0 になります。同様に round(1.5) と round(2.5) は 2 を返します。
割り算の整数部分を得るにはどうしますか?
// 演算子を使います。17 // 5 は 3 を返します。負の数では切り下げになるため、-17 // 5 は -4 になります。小数部分を 0 の方向へ捨てたい場合は、int(-17 / 5) を使います。
Python に三項演算子はありますか?
はい。条件式という形式で書きます。「値1 if 条件 else 値2」の形で、たとえば "偶数" if n % 2 == 0 else "奇数" のように使います。
& と and の違いは何ですか?
and は遅延評価される論理演算子で、& は整数のビット単位の AND、集合では積集合を表す演算子です。条件分岐の if では and を使います。