MENU

JavaScriptで理解するビット演算

目次

はじめに:ビット演算は「試験だけの知識」ではない

ビット演算と聞くと、少し難しそうに感じるかもしれません。

基本情報技術者試験では、AND、OR、XOR、シフト演算などが出題されます。しかし、普段JavaScriptでWebアプリケーションを作っていると、これらを直接書く機会はあまり多くありません。

そのため、「試験には出るけれど、実務ではあまり使わない知識」と思われがちです。

しかし、ビット演算はコンピュータがデータをどのように扱っているのかを理解するうえで、とても重要な考え方です。

たとえば、権限管理、フラグ管理、画像や色の処理、バイナリデータの扱いなどでは、ビット単位の考え方が登場します。たとえ日常的にビット演算子を書かなくても、その仕組みを知っていると、低レイヤーの処理やライブラリの内部実装を理解しやすくなります。

この記事では、JavaScriptのサンプルコードを使いながら、ビット演算の基本を確認していきます。

難しい数式を暗記するのではなく、2進数に直して、1ビットずつ見ていくことを意識すれば、ビット演算はそれほど怖いものではありません。

まずは、ビット演算が「2進数の各桁に対する計算」であることから理解していきましょう。

ビット演算とは

ビット演算とは、数値を2進数として見たときに、各桁のビットに対して行う演算のことです。

コンピュータの内部では、数値や文字、画像などのデータは最終的に0と1の組み合わせで扱われます。この0または1の最小単位を「ビット」と呼びます。

たとえば、10進数の 5 は2進数では次のように表せます。

const value = 5;
console.log(value.toString(2)); // "101"

見やすく4桁で表すと、50101 です。

10進数: 5
2進数 : 0101

同じように、10進数の 3 は2進数では 0011 と表せます。

10進数: 3
2進数 : 0011

通常の足し算や引き算では、数値全体をまとめて計算します。一方で、ビット演算では、2進数の各桁を1つずつ見て計算します。

たとえば、53 をビット単位で並べると、次のようになります。

0101  // 5
0011  // 3

ここで、各桁に対して「両方が1なら1」「どちらかが1なら1」「片方だけが1なら1」といったルールを適用するのがビット演算です。

JavaScriptでは、ビット演算を行うために &|^~<<>>>>> といった演算子が用意されています。

たとえば、& はAND演算を表します。

const result = 5 & 3;
console.log(result); // 1

これは、53 を2進数として見たときに、各桁で「両方が1のところだけを1にする」計算です。

0101  // 5
0011  // 3
----
0001  // 1

このように、ビット演算では10進数のまま結果だけを見ると少しわかりづらいですが、2進数に直して1桁ずつ確認すると理解しやすくなります。

基本情報技術者試験でも、ビット演算の問題は暗記だけで解くよりも、2進数に変換して各桁を追うことが重要です。

次の章では、JavaScriptで使えるビット演算子を一覧で確認し、その後、AND、OR、XORといった代表的な演算を順番に見ていきます。

JavaScriptで使えるビット演算子一覧

JavaScriptには、ビット演算を行うための演算子がいくつか用意されています。

代表的なビット演算子は次のとおりです。

演算子名前意味
&AND演算両方のビットが1なら1
|OR演算どちらかのビットが1なら1
^XOR演算片方だけのビットが1なら1
~NOT演算ビットを反転する
<<左シフトビットを左にずらす
>>符号付き右シフト符号を保ったまま右にずらす
>>>ゼロ埋め右シフト左側を0で埋めて右にずらす

たとえば、AND演算を行う場合は & を使います。

const result = 5 & 3;

console.log(result); // 1

このように、通常の四則演算で使う +- と同じように、数値と数値の間にビット演算子を書きます。

ただし、ビット演算では計算の見方が少し異なります。

5 & 3

という式は、10進数の 53 をそのまま計算しているように見えますが、実際には内部的に2進数のビットとして扱われます。

0101  // 5
0011  // 3
----
0001  // 1

そのため、ビット演算を理解するときは、10進数の結果だけを見るのではなく、2進数に直して各桁を確認することが大切です。

また、JavaScriptのビット演算には注意点があります。

JavaScriptの数値は通常、Number 型として扱われますが、ビット演算を行うときは32ビット整数として処理されます。そのため、小数を含む値や大きすぎる整数に対してビット演算を使う場合は、通常の数値計算とは違った結果になることがあります。

この記事では、まず基本を理解するために、53 のような小さな整数を使って説明していきます。

次の章からは、AND、OR、XOR、NOT、シフト演算を順番に見ていきましょう。

AND / OR / XORを理解する

ここからは、代表的なビット演算であるAND、OR、XORを順番に見ていきます。

この3つは、基本情報技術者試験でもよく登場する重要な演算です。最初は記号だけを見るとわかりにくいかもしれませんが、2進数に直して1桁ずつ確認すると理解しやすくなります。


AND演算:両方が1のビットだけ残す

AND演算は、2つのビットを比べて、両方が 1 の場合だけ 1 になります。

JavaScriptでは & を使います。

const result = 5 & 3;

console.log(result); // 1

10進数の 53 を2進数で表すと、次のようになります。

0101  // 5
0011  // 3
----
0001  // 1

右から1桁ずつ見ると、両方が 1 になっているのは一番右のビットだけです。

そのため、結果は 0001、つまり10進数では 1 になります。

AND演算は、「必要なビットだけを取り出す」処理によく使われます。

たとえば、権限や設定をビットで管理している場合に、特定のフラグが立っているかを確認できます。

const READ = 1;  // 0001
const WRITE = 2; // 0010

const permission = READ | WRITE; // 0011

const canRead = (permission & READ) !== 0;

console.log(canRead); // true

この例では、permissionREAD のビットが含まれているかを & で確認しています。


OR演算:どちらかが1なら1にする

OR演算は、2つのビットを比べて、どちらか一方でも 1 なら 1 になります。

JavaScriptでは | を使います。

const result = 5 | 3;

console.log(result); // 7

2進数で見ると、次のようになります。

0101  // 5
0011  // 3
----
0111  // 7

各桁を見て、どちらかに 1 があれば結果は 1 になります。

そのため、結果は 0111、つまり10進数では 7 です。

OR演算は、「フラグを追加する」処理に使いやすい演算です。

const READ = 1;   // 0001
const WRITE = 2;  // 0010
const DELETE = 4; // 0100

let permission = READ;       // 0001
permission = permission | WRITE; // 0011

console.log(permission); // 3

この例では、最初に READ だけを持っていた permission に、WRITE の権限を追加しています。

実務のコードでは、フラグ管理や設定値の組み合わせを表現するときに、この考え方が使われることがあります。


XOR演算:片方だけが1なら1にする

XOR演算は、2つのビットを比べて、片方だけが 1 の場合に 1 になります。

JavaScriptでは ^ を使います。

const result = 5 ^ 3;

console.log(result); // 6

2進数で見ると、次のようになります。

0101  // 5
0011  // 3
----
0110  // 6

XORは、「同じなら0、違えば1」と考えると理解しやすいです。

たとえば、一番右のビットはどちらも 1 なので、結果は 0 になります。右から2番目のビットは 01 で異なるため、結果は 1 になります。

XOR演算は、ANDやORに比べると日常のWeb開発で直接使う機会は少ないかもしれません。

ただし、ビットの切り替えや、差分の検出、簡単な暗号化の考え方などにつながる重要な演算です。

たとえば、同じ値で2回XORを行うと元に戻る、という特徴があります。

const value = 5;
const key = 3;

const encoded = value ^ key;
const decoded = encoded ^ key;

console.log(encoded); // 6
console.log(decoded); // 5

この性質は、XORの大きな特徴です。

もちろん、実際の暗号化ではこのような単純な処理だけでは不十分ですが、「同じ操作をもう一度行うと元に戻る」という考え方を理解する例としては役立ちます。


AND、OR、XORは、それぞれ次のように整理できます。

演算条件使いどころの例
AND両方が1なら1特定のビットを取り出す
ORどちらかが1なら1フラグを追加する
XOR片方だけが1なら1ビットの切り替え、差分の検出

ビット演算では、10進数の結果だけを見ると直感的にわかりにくいことがあります。

迷ったときは、数値を2進数に直して、各桁を1つずつ確認するのが基本です。

NOT / シフト演算を理解する

AND、OR、XORは、2つの値を比べてビットごとに計算する演算でした。

一方、NOT演算やシフト演算は、1つの値に対してビットを反転したり、左右にずらしたりする演算です。

ここでは、JavaScriptでのNOT演算とシフト演算を順番に見ていきましょう。


NOT演算:ビットを反転する

NOT演算は、ビットの 01 を反転する演算です。

JavaScriptでは ~ を使います。

const result = ~5;

console.log(result); // -6

ここで、5 のビットを反転するなら、結果は単純に 01011010 になって 10 になるのではないか、と思うかもしれません。

しかし、JavaScriptのビット演算では、数値は32ビットの符号付き整数として扱われます。

つまり、5 は実際には次のような32ビットの値として見られます。

00000000000000000000000000000101

これをNOT演算で反転すると、次のようになります。

11111111111111111111111111111010

左端のビットが 1 になっているため、これは負の数として扱われます。

JavaScriptでは、~x の結果は -(x + 1) と考えると理解しやすいです。

console.log(~5);  // -6
console.log(~10); // -11
console.log(~0);  // -1

なぜこのような結果になるのかを深く理解するには、「2の補数」という負の数の表現方法が関係します。

基本情報技術者試験でも2の補数は重要ですが、ここではまず「JavaScriptのビット演算では32ビット整数として扱われる」「NOT演算は単純な見た目よりも結果がわかりにくい」という点を押さえておきましょう。


左シフト:ビットを左にずらす

左シフトは、ビットを指定した数だけ左にずらす演算です。

JavaScriptでは << を使います。

const result = 3 << 1;

console.log(result); // 6

10進数の 3 は、2進数では 0011 です。

0011  // 3

これを左に1ビットずらすと、次のようになります。

0110  // 6

結果は 6 です。

左に1ビットずらすと、値はおおよそ2倍になります。

console.log(3 << 1); // 6
console.log(3 << 2); // 12
console.log(3 << 3); // 24

3 << 2 は、3を左に2ビットずらすという意味です。左に2ビットずらすと、2倍を2回行うため、結果は4倍になります。

3 << 1  // 3 * 2 = 6
3 << 2  // 3 * 4 = 12
3 << 3  // 3 * 8 = 24

このように、左シフトは「2の倍数をかける処理」として理解できます。

ただし、実務のJavaScriptで単純な掛け算の代わりにシフト演算を使う必要は、ほとんどありません。読みやすさを考えると、通常は * 2* 4 と書いた方が意図が伝わりやすいです。


右シフト:ビットを右にずらす

右シフトは、ビットを指定した数だけ右にずらす演算です。

JavaScriptでは、主に >>>>> の2種類があります。

まずは、符号付き右シフトである >> を見てみましょう。

const result = 8 >> 1;

console.log(result); // 4

10進数の 8 は、2進数では 1000 です。

1000  // 8

これを右に1ビットずらすと、次のようになります。

0100  // 4

結果は 4 です。

右に1ビットずらすと、値はおおよそ2で割った結果になります。

console.log(8 >> 1); // 4
console.log(8 >> 2); // 2
console.log(8 >> 3); // 1

整数の範囲では、右シフトは「2で割る処理」に近いと考えられます。

ただし、小数は表現されません。

console.log(7 >> 1); // 3

7 / 23.5 ですが、7 >> 1 の結果は 3 です。

このように、右シフトでは小数部分が切り捨てられるような結果になります。


>>>>> の違い

JavaScriptには、右シフトとして >>>>> の2種類があります。

違いがわかりやすく出るのは、負の数を扱う場合です。

console.log(-8 >> 1);  // -4
console.log(-8 >>> 1); // 2147483644

>> は符号付き右シフトです。

符号を保ったまま右にずらすため、負の数は負の数のまま扱われます。

一方、>>> はゼロ埋め右シフトです。

左側を 0 で埋めながら右にずらすため、負の数に対して使うと大きな正の数になることがあります。

最初のうちは、次のように整理しておくとよいでしょう。

演算子名前特徴
>>符号付き右シフト符号を保って右にずらす
>>>ゼロ埋め右シフト左側を0で埋めて右にずらす

基本情報技術者試験では、シフト演算そのものの理解が問われることが多いです。一方、JavaScriptでコードを書く場合は、>>>>> の違いも押さえておくと、言語仕様に踏み込んだ理解につながります。


NOT演算とシフト演算は、AND、OR、XORに比べると少しクセがあります。

特にJavaScriptでは、ビット演算時に32ビット整数として扱われるため、通常の数値計算とは異なる結果になることがあります。

まずは、次のポイントを押さえておきましょう。

演算意味覚え方
~ビットを反転する~x-(x + 1)
<<左にずらす2倍、4倍、8倍のイメージ
>>右にずらす符号を保って2で割るイメージ
>>>右にずらす左側を0で埋める

次の章では、ここまで学んだビット演算が、実務のどのような場面で役立つのかを見ていきます。

実務での使いどころ

ここまで、AND、OR、XOR、NOT、シフト演算といったビット演算を見てきました。

では、これらの知識はWeb開発の実務でどのように役立つのでしょうか。

正直に言うと、一般的なWebアプリケーション開発で、ビット演算を毎日のように書くことは多くありません。

フォーム処理、API通信、画面表示、データベース操作などでは、ビット演算よりも文字列、配列、オブジェクト、SQLなどを扱う場面の方が多いでしょう。

それでも、ビット演算の考え方を知っていると、コンピュータがデータをどのように扱っているのかを理解しやすくなります。

代表的な使いどころの1つが、フラグ管理です。

たとえば、ユーザーの権限を次のようにビットで表すことができます。

const READ = 1;    // 0001
const WRITE = 2;   // 0010
const DELETE = 4;  // 0100

const permission = READ | WRITE;

const canRead = (permission & READ) !== 0;
const canWrite = (permission & WRITE) !== 0;
const canDelete = (permission & DELETE) !== 0;

console.log(canRead);   // true
console.log(canWrite);  // true
console.log(canDelete); // false

この例では、READWRITEDELETE という権限を、それぞれ別のビットで表しています。

READ | WRITE とすることで、読み取り権限と書き込み権限を1つの数値にまとめています。

そして、permission & READ のようにAND演算を使うことで、特定の権限が含まれているかを確認できます。

もちろん、実際のWebアプリケーションでは、権限を文字列や配列、ロール名で管理する方が読みやすい場合も多いです。

const permissions = ["read", "write"];

const canRead = permissions.includes("read");

console.log(canRead); // true

そのため、何でもビット演算で書けばよいわけではありません。

大切なのは、「複数の状態を1つの数値にまとめる考え方」があると知っておくことです。

ビット演算は、他にも画像処理や色の操作、バイナリデータの解析、通信プロトコルの理解などで登場します。

たとえば、色を表す値は、赤、緑、青の情報をビット単位で持っていることがあります。

const color = 0xff3366;

const red = (color >> 16) & 0xff;
const green = (color >> 8) & 0xff;
const blue = color & 0xff;

console.log(red);   // 255
console.log(green); // 51
console.log(blue);  // 102

この例では、0xff3366 という色の値から、赤、緑、青の成分を取り出しています。

>> で必要な位置までビットをずらし、& 0xff で下位8ビットだけを取り出しています。

このような処理は、普段のWeb制作ではライブラリが隠してくれていることも多いです。

しかし、Canvas、画像処理、WebGL、バイナリファイルの読み取りなど、少し低レイヤー寄りの処理に踏み込むと、ビット演算の知識が役立ちます。

また、基本情報技術者試験では、ビット演算そのものが問題として出題されます。

実務で頻繁に書かないとしても、ビット演算を理解することは、コンピュータの内部表現を理解するための良い入口になります。

「試験のためだけに覚える」のではなく、「データは最終的に0と1で扱われている」という感覚を身につけるための知識として捉えると、学ぶ意味が見えやすくなるはずです。

基本情報技術者試験での出題ポイント

ビット演算は、基本情報技術者試験でもよく問われるテーマです。

特に重要なのは、演算子の記号を暗記することよりも、2進数に直して1ビットずつ結果を追えるようになることです。

たとえば、次のような式が出てきたとします。

5 & 3

10進数のまま見ると、なぜ結果が 1 になるのか少しわかりにくいかもしれません。

しかし、2進数に直すと考えやすくなります。

0101  // 5
0011  // 3
----
0001  // 1

このように、各桁を順番に確認すれば、AND演算の結果を落ち着いて求めることができます。

試験では、AND、OR、XORの結果を求める問題だけでなく、マスク処理やシフト演算が絡む問題も出題されます。

マスク処理とは、特定のビットだけを取り出したり、不要なビットを無視したりする考え方です。

たとえば、下位4ビットだけを取り出したい場合は、1111 にあたる値でAND演算を行います。

const value = 0b10101101;
const lower4Bits = value & 0b00001111;

console.log(lower4Bits.toString(2)); // "1101"

この例では、0b00001111 を使って、下位4ビットだけを残しています。

10101101
00001111
--------
00001101

基本情報技術者試験では、このように「どのビットを残したいのか」「どのビットを0にしたいのか」を読み取る力が大切です。

シフト演算については、左シフトが2倍、4倍、8倍のような計算に対応し、右シフトが2で割るような計算に対応する点を押さえておきましょう。

console.log(3 << 1); // 6
console.log(3 << 2); // 12

console.log(8 >> 1); // 4
console.log(8 >> 2); // 2

ただし、JavaScriptではビット演算時に32ビット整数として扱われる点や、>>>>> の違いなど、言語特有の注意点もあります。

試験対策としては、まずは次のポイントを押さえておくとよいでしょう。

項目押さえるポイント
AND両方が1なら1。特定のビットを取り出す
ORどちらかが1なら1。フラグを立てる
XOR片方だけが1なら1。同じなら0、違えば1
NOT0と1を反転する
左シフトビットを左へずらす。2倍、4倍のイメージ
右シフトビットを右へずらす。2で割るイメージ
マスク処理必要なビットだけを残す考え方

まとめ:ビット演算は低レイヤー理解の入り口

この記事では、JavaScriptのサンプルコードを使いながら、ビット演算の基本を見てきました。

ビット演算は、普段のWebアプリケーション開発で毎日使うものではないかもしれません。

しかし、コンピュータが数値やデータを0と1で扱っていることを理解するうえで、とても重要な知識です。

AND、OR、XOR、NOT、シフト演算は、最初は記号が多くて難しく感じるかもしれません。

それでも、2進数に直して1桁ずつ確認すれば、決して特別な計算ではありません。

ビット演算を理解するコツ
= 10進数のまま考えず、2進数に直して各桁を見る

また、実務ではフラグ管理、色の操作、画像処理、バイナリデータの解析など、少し低レイヤー寄りの処理でビット演算の考え方が役立ちます。

基本情報技術者試験の対策としても、Webエンジニアとしての基礎理解としても、ビット演算は押さえておきたいテーマです。

まずは、AND、OR、XORの結果を2進数で追えるようになるところから始めてみましょう。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

20代前半に、ゲームボーイアドバンス、ニンテンドーDS、Wii向けソフトの開発に携わりました。

その後、20代後半にかけては組み込み系エンジニアとして、主にサーバーソフトウェアの開発を経験。

30代からはWebエンジニアとして、さまざまなWebサービスの開発に携わってきました。

現在は40代となり、ゲーム開発、組み込み開発、Web開発で培った経験を活かしながら、技術をわかりやすく伝える活動にも取り組んでいます。

コメント

コメントする

CAPTCHA


目次