0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【ビット演算入門】ビット演算の仕組み

Last updated at Posted at 2024-09-24

はじめに

最近、ビット演算について学ぶ機会がありました。最初は難しそうに思えたビット演算ですが、実はとてもシンプルで強力なツールであることがわかりました。ここではビット演算について、仕組みや利用シーンについて勉強したことをシェアしていきます。

ビット演算とは?

ビット演算とは、数値を ビット単位 で操作する演算方法です。数値はコンピュータ内部で 2進数(0と1)で表されているため、ビットごとに計算を行うことで、効率的な処理が可能です。

各桁ごとに計算される

ビット演算は、各ビット(桁)ごとに演算が行われます。この動作は、10進数の演算において 同じ位同士を計算するのをイメージするとわかりやすいです。10進数での加算では、1の位、10の位、100の位と順に計算が行われますが、ビット演算では2進数の各ビットが順番に計算されます。

例えば、2進数の 5(0101)と 3(0011)を AND演算&)する場合、対応するビット同士を比較し、両方が1なら1、それ以外は0となります。

  0101   (5)
& 0011   (3)
  ----
  0001   (1)

ビット演算の基本的な操作

ビット演算にはいくつかの基本的な演算子があります。それぞれ、2進数の各ビットごとに計算が行われます。

AND(&)

両方のビットが 1 である場合、結果も 1 になります。それ以外は 0 です。
例:5 & 3 → 0101 & 0011 = 0001 → 結果は 1

  0101   (5)
& 0011   (3)
  ----
  0001   (1)

OR(|)

どちらか一方のビットが 1 であれば、結果は 1 になります。
例:5 | 3 → 0101 | 0011 = 0111 → 結果は 7

  0101   (5)
| 0011   (3)
  ----
  0111   (7)

XOR(^)

ビットが異なる場合に 1 になります。同じ場合は 0 です。
例:5 ^ 3 → 0101 ^ 0011 = 0110 → 結果は 6

  0101   (5)
^ 0011   (3)
  ----
  0110   (6)

左シフト(<<)

ビットを左にシフトし、右に 0 を埋めます。これは数値を2倍にする操作と等価です。
例:5 << 1 → 0101 << 1 = 1010 → 結果は 10

5 << 1
=> 0101 << 1 //0101の各桁の値を1つ左にずらす
=> 1010 (10)

右シフト(>>)

ビットを右にシフトし、符号ビットで埋めます。これは数値を2で割る操作と同じです(小数点以下は切り捨て)。
例:5 >> 1 → 0101 >> 1 = 0010 → 結果は 2

5 >> 1
=> 0101 >> 1 //0101の各桁の値を1つ右にずらす
=> 0010 (2)

具体的なビット演算の利用シーン

1. 偶数・奇数の判定

ビット演算を使うと、ある数値が 偶数か奇数か を簡単に判定できます。二進数では、偶数は最下位ビットが 0、奇数は 1 になっているため、最下位ビットを確認するだけで判定が可能です。

具体例

function isEven(num: number): boolean {
    return (num & 1) === 0;
}

console.log(isEven(4));  // true(偶数)
console.log(isEven(5));  // false(奇数)
  • 偶数の最下位ビットは常に 0 で、奇数の最下位ビットは 1 です
  • num & 1 で最下位ビットが 01 かを確認します

2. 2で割る、掛ける操作

ビットシフト演算を使って、数値を 2で割る、掛ける 操作を高速に行うことができます。右に1ビットシフトすると、数値が2で割られ、左に1ビットシフトすると、数値が2で掛けられ、小数点以下は切り捨てられます。

右に1ビットシフトして 2で割る

function divideByTwo(num: number): number {
    return num >> 1;
}

console.log(divideByTwo(4));  // 2
console.log(divideByTwo(5));  // 2(小数点以下は切り捨て)

num >> 1: 数値を右に1ビットシフトすると、2で割る操作が行われます。小数点以下は切り捨てられます

左に1ビットシフトして 2で掛ける 操作

function multiplyByTwo(num: number): number {
    return num << 1;
}

console.log(multiplyByTwo(4));  // 8(4 × 2 = 8)
console.log(multiplyByTwo(7));  // 14(7 × 2 = 14)

num << 1: 数値を左に1ビットシフトすると、2で掛ける操作が行われます。

  • 右にビットシフト(>>): 数値を2で割る操作と同じです。ビットを1つ右に移動することで、数値が半分になります(小数点以下は切り捨てられます)
  • 左にビットシフト(<<): 数値を2で掛ける操作と同じです。ビットを1つ左に移動することで、数値が2倍になります

その他の利用シーン

ビット演算は、奇数・偶数判定や2の倍数の計算以外にもさまざまな場面で効率的に利用できます。

1. ビットマスクを使った特定のビットの操作

ビットマスクを用いることで、特定のビットを確認・設定・リセットすることが可能です。フラグ管理や権限のチェックなどで利用されます。

利用シーン例: フラグのON/OFF、権限管理、特定ビットの確認。


2. フラグ管理

1つの数値で複数のフラグ(ON/OFF状態)を管理し、効率的に状態を制御できます。ゲーム開発や設定の保存で利用されます。

利用シーン例: 複数の設定を1つの変数で管理、状態フラグの制御。


3. ビットカウント(1のビット数を数える)

ある数値に含まれる1ビットの数(ハミング重量)を数えることで、データ処理や圧縮に活用されます。

利用シーン例: エラーチェック、圧縮アルゴリズム、データ解析。


4. ビット回転(ローテーション)

ビットを回転させる操作は、暗号化やハッシュ関数で使われ、データの順序を効率的に操作できます。

利用シーン例: 暗号化アルゴリズム、ハッシュ関数、データシフト。


5. 符号反転(負数の計算)

ビット反転と加算を使って、効率的に符号を反転させることが可能です。負の数の計算に活用されます。

利用シーン例: 数値の符号反転、負の数計算。

まとめ

ちょっととっつきにくいビット演算ですが、10進数と同じようなことが2進数で行われていることがわかれば、理解しやすいと思います。ビット演算は、各ビット(桁)ごとに計算が行われるため、10進数での桁ごとの計算と同じような感覚で理解できます。偶数・奇数の判定や2の倍数の操作に優れている理由は、各ビットが2進数の桁に対応しているためです。
10進数に変換しない分高速に処理できるため、処理速度を突き詰めて行くと、ビット演算の理解は大切だなと勉強してみて思いました。誰かの参考になれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?