Pythonビット演算子完全ガイド – &・|・^・~・<<・>>の使い方と活用法
ビット演算子とは?
Python のビット演算子は、数値をバイナリ(2進数)レベルで操作するための演算子です。整数の各ビットに対して論理演算やシフト操作を行い、高速な計算やフラグ管理、暗号化処理などで威力を発揮します。
基本的なビット演算子一覧
1. AND演算子(&)
両方のビットが1の場合のみ1を返します。
# 基本的なAND演算
a = 12 # 1100 (2進数)
b = 8 # 1000 (2進数)
result = a & b # 1000 = 8
print(f"{a} & {b} = {result}") # 12 & 8 = 8
# バイナリ表示で確認
print(f"{bin(a)} & {bin(b)} = {bin(result)}")
# 0b1100 & 0b1000 = 0b1000
2. OR演算子(|)
どちらかのビットが1の場合に1を返します。
# 基本的なOR演算
a = 12 # 1100 (2進数)
b = 8 # 1000 (2進数)
result = a | b # 1100 = 12
print(f"{a} | {b} = {result}") # 12 | 8 = 12
# より明確な例
x = 5 # 0101
y = 3 # 0011
result = x | y # 0111 = 7
print(f"{x} | {y} = {result}") # 5 | 3 = 7
3. XOR演算子(^)
ビットが異なる場合のみ1を返します。
# 基本的なXOR演算
a = 12 # 1100
b = 8 # 1000
result = a ^ b # 0100 = 4
print(f"{a} ^ {b} = {result}") # 12 ^ 8 = 4
# XORの特性:同じ数でXORすると0
x = 42
result = x ^ x
print(f"{x} ^ {x} = {result}") # 42 ^ 42 = 0
4. NOT演算子(~)
すべてのビットを反転させます。
# 基本的なNOT演算
a = 5 # 0101
result = ~a # ...11111010 = -6
print(f"~{a} = {result}") # ~5 = -6
# 8ビットでの例
b = 255 # 11111111
result = ~b # -256
print(f"~{b} = {result}") # ~255 = -256
5. 左シフト演算子(<<)
ビットを左にシフト(2のn乗倍)します。
# 基本的な左シフト
a = 5 # 0101
result = a << 1 # 1010 = 10
print(f"{a} << 1 = {result}") # 5 << 1 = 10
# 複数ビットシフト
result = a << 2 # 10100 = 20
print(f"{a} << 2 = {result}") # 5 << 2 = 20
# 2のn乗計算
power = 2 ** 3
shift = 1 << 3
print(f"2^3 = {power}, 1<<3 = {shift}") # 2^3 = 8, 1<<3 = 8
6. 右シフト演算子(>>)
ビットを右にシフト(2のn乗で割る)します。
# 基本的な右シフト
a = 20 # 10100
result = a >> 1 # 01010 = 10
print(f"{a} >> 1 = {result}") # 20 >> 1 = 10
# 複数ビットシフト
result = a >> 2 # 00101 = 5
print(f"{a} >> 2 = {result}") # 20 >> 2 = 5
# 整数除算との比較
div_result = 20 // 4
shift_result = 20 >> 2
print(f"20//4 = {div_result}, 20>>2 = {shift_result}") # 両方とも5
ビット演算の実践的な応用
1. フラグ管理システム
# 権限フラグの定義
READ = 1 # 0001
WRITE = 2 # 0010
EXECUTE = 4 # 0100
DELETE = 8 # 1000
def set_permission(current, permission):
return current | permission
def remove_permission(current, permission):
return current & ~permission
def has_permission(current, permission):
return (current & permission) == permission
# 使用例
permissions = 0 # 初期状態
permissions = set_permission(permissions, READ | WRITE)
print(f"読み取り権限あり: {has_permission(permissions, READ)}") # True
print(f"削除権限あり: {has_permission(permissions, DELETE)}") # False
2. 高速な偶数・奇数判定
def is_even_fast(n):
return (n & 1) == 0
def is_odd_fast(n):
return (n & 1) == 1
# 使用例
numbers = [10, 15, 22, 33, 44]
for num in numbers:
result = "偶数" if is_even_fast(num) else "奇数"
print(f"{num}は{result}")
3. 2の累乗判定
def is_power_of_two(n):
return n > 0 and (n & (n - 1)) == 0
# 使用例
test_numbers = [1, 2, 4, 6, 8, 15, 16, 32]
for num in test_numbers:
result = is_power_of_two(num)
print(f"{num}は2の累乗: {result}")
暗号化・セキュリティでの活用
1. 簡単なXOR暗号化
def xor_encrypt(text, key):
return ''.join(chr(ord(char) ^ key) for char in text)
def xor_decrypt(encrypted, key):
return xor_encrypt(encrypted, key) # XORは可逆
# 使用例
message = "Hello World"
key = 123
encrypted = xor_encrypt(message, key)
decrypted = xor_decrypt(encrypted, key)
print(f"元のメッセージ: {message}")
print(f"暗号化: {encrypted}")
print(f"復号化: {decrypted}")
2. ハッシュ関数での活用
def simple_hash(text):
hash_value = 0
for char in text:
hash_value = (hash_value << 5) ^ ord(char)
hash_value &= 0xFFFFFFFF # 32ビット制限
return hash_value
# 使用例
strings = ["apple", "banana", "cherry"]
for s in strings:
hash_val = simple_hash(s)
print(f"'{s}' のハッシュ値: {hash_val}")
パフォーマンス最適化
1. 高速な乗算・除算
import timeit
def multiply_by_power_of_two(n, power):
return n << power
def divide_by_power_of_two(n, power):
return n >> power
# パフォーマンス比較
n = 1000
# 通常の計算
time1 = timeit.timeit(lambda: n * 8, number=1000000)
# ビットシフト
time2 = timeit.timeit(lambda: n << 3, number=1000000)
print(f"通常の乗算: {time1:.6f}秒")
print(f"ビットシフト: {time2:.6f}秒")
2. 配列インデックスの最適化
def next_power_of_two(n):
if n <= 1:
return 1
n -= 1
n |= n >> 1
n |= n >> 2
n |= n >> 4
n |= n >> 8
n |= n >> 16
return n + 1
# 使用例
test_values = [3, 7, 15, 20, 100]
for val in test_values:
result = next_power_of_two(val)
print(f"{val} → {result}")
ビットマスクの活用
1. 状態管理システム
class TaskStatus:
PENDING = 1 # 0001
RUNNING = 2 # 0010
COMPLETED = 4 # 0100
FAILED = 8 # 1000
class Task:
def __init__(self):
self.status = 0
def add_status(self, status):
self.status |= status
def remove_status(self, status):
self.status &= ~status
def has_status(self, status):
return (self.status & status) != 0
def get_status_list(self):
statuses = []
if self.has_status(TaskStatus.PENDING):
statuses.append("PENDING")
if self.has_status(TaskStatus.RUNNING):
statuses.append("RUNNING")
if self.has_status(TaskStatus.COMPLETED):
statuses.append("COMPLETED")
if self.has_status(TaskStatus.FAILED):
statuses.append("FAILED")
return statuses
# 使用例
task = Task()
task.add_status(TaskStatus.PENDING | TaskStatus.RUNNING)
print(f"現在の状態: {task.get_status_list()}")
2. RGB色の操作
def rgb_to_int(r, g, b):
return (r << 16) | (g << 8) | b
def int_to_rgb(color):
r = (color >> 16) & 0xFF
g = (color >> 8) & 0xFF
b = color & 0xFF
return r, g, b
def adjust_brightness(color, factor):
r, g, b = int_to_rgb(color)
r = min(255, int(r * factor))
g = min(255, int(g * factor))
b = min(255, int(b * factor))
return rgb_to_int(r, g, b)
# 使用例
red = rgb_to_int(255, 0, 0)
print(f"赤色の整数値: {red}")
print(f"RGB分解: {int_to_rgb(red)}")
darker_red = adjust_brightness(red, 0.5)
print(f"暗い赤: {int_to_rgb(darker_red)}")
データ構造での活用
1. ビットセット(集合の表現)
class BitSet:
def __init__(self, size=32):
self.bits = 0
self.size = size
def add(self, element):
if 0 <= element < self.size:
self.bits |= (1 << element)
def remove(self, element):
if 0 <= element < self.size:
self.bits &= ~(1 << element)
def contains(self, element):
if 0 <= element < self.size:
return (self.bits & (1 << element)) != 0
return False
def to_list(self):
return [i for i in range(self.size) if self.contains(i)]
# 使用例
bit_set = BitSet(10)
bit_set.add(1)
bit_set.add(3)
bit_set.add(7)
print(f"セットの要素: {bit_set.to_list()}") # [1, 3, 7]
2. ブルームフィルタの基礎
class SimpleBloomFilter:
def __init__(self, size=1000):
self.size = size
self.bit_array = 0
def _hash1(self, item):
return hash(item) % self.size
def _hash2(self, item):
return (hash(item) * 17) % self.size
def add(self, item):
h1 = self._hash1(item)
h2 = self._hash2(item)
self.bit_array |= (1 << h1)
self.bit_array |= (1 << h2)
def might_contain(self, item):
h1 = self._hash1(item)
h2 = self._hash2(item)
return (self.bit_array & (1 << h1)) and (self.bit_array & (1 << h2))
# 使用例
bloom = SimpleBloomFilter(100)
bloom.add("apple")
bloom.add("banana")
print(f"'apple'が含まれる可能性: {bloom.might_contain('apple')}")
print(f"'orange'が含まれる可能性: {bloom.might_contain('orange')}")
よくある間違いと対処法
1. 負数での右シフト
# 負数の右シフトに注意
positive = 8
negative = -8
print(f"正数: {positive} >> 1 = {positive >> 1}") # 4
print(f"負数: {negative} >> 1 = {negative >> 1}") # -4
# 符号なしシフトが必要な場合
def unsigned_right_shift(n, bits):
return (n % (1 << 32)) >> bits
print(f"符号なしシフト: {unsigned_right_shift(-8, 1)}")
2. ビット演算子と論理演算子の混同
# 間違い:論理演算子を使用
a, b = 5, 3
# wrong = a and b # これは論理演算
# 正しい:ビット演算子を使用
correct = a & b
print(f"{a} & {b} = {correct}") # 5 & 3 = 1
# ブール値での違い
bool1, bool2 = True, False
logical_and = bool1 and bool2 # False
bitwise_and = bool1 & bool2 # False (この場合は同じ)
print(f"論理AND: {logical_and}, ビットAND: {bitwise_and}")
3. シフト演算での桁あふれ
# 大きなシフト値に注意
large_number = 1000000
safe_shift = large_number << 10 # 問題なし
print(f"安全なシフト: {safe_shift}")
# シフト量が大きすぎる場合
try:
# 非常に大きなシフトは避ける
huge_shift = 1 << 1000 # Pythonは任意精度整数なので可能
print(f"巨大な数の桁数: {len(str(huge_shift))}")
except MemoryError:
print("メモリ不足")
デバッグとテストのコツ
1. ビット演算の可視化
def visualize_bits(number, width=8):
binary = bin(number)[2:].zfill(width)
return f"{number:3d} = {binary}"
def show_operation(a, b, op_name, result):
print(f"{visualize_bits(a)}")
print(f"{visualize_bits(b)}")
print(f"{'=' * 15} {op_name}")
print(f"{visualize_bits(result)}")
print()
# 使用例
a, b = 12, 8
show_operation(a, b, "AND", a & b)
show_operation(a, b, "OR", a | b)
show_operation(a, b, "XOR", a ^ b)
2. ビット演算のテストケース
def test_bit_operations():
# AND演算のテスト
assert (5 & 3) == 1
assert (15 & 7) == 7
# OR演算のテスト
assert (5 | 3) == 7
assert (8 | 4) == 12
# XOR演算のテスト
assert (5 ^ 3) == 6
assert (x := 42) ^ x == 0 # 自分自身とのXOR
# シフト演算のテスト
assert (1 << 3) == 8
assert (16 >> 2) == 4
print("全てのテストが通過しました")
test_bit_operations()
まとめ
Python のビット演算子を効果的に活用するポイント:
- 基本演算子の理解:
&,|,^,~,<<,>>の動作を正確に把握 - パフォーマンス活用: 2の累乗計算や偶数判定での高速化
- フラグ管理: 複数の状態を効率的に管理
- 暗号化・ハッシュ: セキュリティ関連処理での活用
- データ構造: ビットセットやブルームフィルタなどの実装
ビット演算子をマスターすることで、高性能で効率的なPythonプログラムが作成できるようになります。
■プロンプトだけでオリジナルアプリを開発・公開してみた!!
■AI時代の第一歩!「AI駆動開発コース」はじめました!
テックジム東京本校で先行開始。
■テックジム東京本校
「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。
<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。
<月1開催>放送作家による映像ディレクター養成講座
<オンライン無料>ゼロから始めるPython爆速講座





