1.

Python 算術演算子|/ と // の違い・負数の剰余・Decimal での誤差対策

編集
この記事の要点
  • 算術演算子は + - * / // % ** の 7 つ
  • / は常に float。整数で欲しいときは //(切り捨て除算)
  • //%負数で 0 方向ではなく下方向に丸める-7 // 2-4-7 % 21
  • int に上限は無い(任意精度)。オーバーフローしない代わりに巨大な値は遅くなる
  • 小数の誤差が困る場面は decimal.Decimalfractions.Fraction を使う

一覧

演算子意味結果
+加算7 + 29
-減算7 - 25
*乗算7 * 214
/除算(必ず float)7 / 23.5
//切り捨て除算7 // 23
%剰余7 % 21
**べき乗7 ** 249

負数での //%

ここが他言語といちばん違うところです。Python の //負の無限大方向へ切り捨て(床関数)、% の符号は右オペランドに合わせます。

print(7 // 2, 7 % 2)      # 3 1
print(-7 // 2, -7 % 2)    # -4 1     ← -3 ではなく -4、余りは正
print(7 // -2, 7 % -2)    # -4 -1    ← 余りの符号は右側に合う

# 0 方向に丸めたいときは int() か math.trunc()
import math
print(int(-7 / 2), math.trunc(-7 / 2))   # -3 -3

# 商と余りを同時に得る
print(divmod(-7, 2))      # (-4, 1)

a == (a // b) * b + (a % b) が常に成り立つ」という関係は保たれます。剰余が必ず非負になるので、循環インデックスの計算に負数を渡しても安全です。

days = ["月", "火", "水", "木", "金", "土", "日"]
print(days[-3 % 7])   # 金   ← 負のシフトでも例外にならない

int はオーバーフローしない

print(2 ** 100)
# 1267650600228229401496703205376

import sys
print(sys.maxsize)          # プラットフォーム依存の目安値であって上限ではない
print(sys.maxsize + 1)      # 問題なく計算できる

上限が無い代わりに、桁が増えるほど演算コストが上がります。速度が要る数値計算では numpy の固定幅整数を使いますが、そちらはオーバーフローで折り返す点に注意してください。

ゼロ除算

try:
    1 / 0
except ZeroDivisionError as e:
    print(e)        # division by zero

try:
    1 % 0
except ZeroDivisionError as e:
    print(e)        # integer modulo by zero

# float は inf にはならず、同じく例外
# ただし numpy は警告を出して inf / nan を返す(挙動が違う)

浮動小数の誤差

print(0.1 + 0.2)              # 0.30000000000000004
print(0.1 + 0.2 == 0.3)       # False

import math
print(math.isclose(0.1 + 0.2, 0.3))   # True  ← 比較はこれ

from decimal import Decimal
print(Decimal("0.1") + Decimal("0.2"))   # 0.3   ← 金額計算はこちら

from fractions import Fraction
print(Fraction(1, 3) + Fraction(1, 6))   # 1/2

Decimal文字列から作るのが要点です。Decimal(0.1) と書くと float の誤差をそのまま取り込んでしまいます。

丸めの注意

print(round(0.5), round(1.5), round(2.5))   # 0 2 2
# Python の round は「偶数丸め(銀行家の丸め)」。四捨五入ではない

from decimal import Decimal, ROUND_HALF_UP
print(Decimal("2.5").quantize(Decimal("1"), rounding=ROUND_HALF_UP))   # 3

関連

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 算術演算子
  2. 文字列演算子
  3. 代入演算子
  4. 比較演算子
  5. 論理演算子
  6. ビット演算子

最近更新/作成されたページ