Python ビットシフトと加減算の演算子の優先順位

気づいてしまえば何ということもない話だったが、解決までに結構時間を食ってしまったので、忘れないようにメモしておく。

Python演算子で、ビットシフト演算子は加算・減算演算子よりも優先順位が低い。

演算子の優先順位の一覧は、公式ドキュメントの以下のセクションにあるので参照のこと。
6. 式 (expression) — Python 3.7.3 ドキュメント


以下、具体例。

下の例で、aを8ビットシフトした数値と、bを4ビットシフトした数値の和を求めたいとする。(この記事を通して、シフト方向は左とする)
手計算では、答えは3 * 256 + 5 * 16 = 768 + 80 = 848 となる。

a = 3
b = 5
x1 = a << 8 + b << 4
print("x1={}".format(x1))

x2 = (a << 8) + (b << 4)
print("x2={}".format(x2))

x3 = a * 2 ** 8 + b * 2 ** 4
print("x3={}".format(x3))


出力:
x1=393216  # 期待と違う!
x2=848
x3=848

x1 がおかしな値になった理由は、加算演算子のほうがビットシフト演算子よりも優先順位が高いせいである。x1の式の計算順序は次のようになる。

  • まず、8 + bが先に計算される。 8+5=13
  • a << 13 << 4の2つの演算子の優先順位は同じなので、左から先に計算される。 3 << 13 = 24576
  • 24576 << 4演算子はただ一つしかないので、それが計算される。24576 << 4 = 393216

2番めで左から先に計算される根拠は、公式ドキュメントの先ほどと同じ箇所にある以下の記述である。
6. 式 (expression) — Python 3.7.3 ドキュメント

同じボックス内の演算子は、左から右へとグループ化されます (例外として、べき乗は右から左にグループ化されます)。

「aを8ビットシフトした数値と、bを4ビットシフトした数値の和」を求めたい場合は、x2のようにカッコを付ける必要がある。

また、x3のように書いてもよい(計算速度については考慮していない)。乗算演算子よりもべき乗演算子のほうが優先度が高い。したがって、a * 2 ** 8は期待通りにべき乗が先に計算される。