JavaScript/符号なし右シフト代入演算子
>>>=(Unsigned Right Shift Assignment 符号なし右シフト代入演算子)は、左辺の値を右に指定したビット数だけ符号なしシフトし、その結果を左辺に代入する代入演算子です。この演算子を使用することで、ビット操作と代入を一度に行うことができます[1]。
構文
[編集]lhs >>>= rhs
lhs: 代入先の変数やプロパティや配列要素参照などの左辺値式rhs: 右シフトするビット数を表す右辺の式
この演算子は次のコードと同等です:
lhs = lhs >>> rhs
ただし、lhs は一度だけ評価されます。
例
[編集]基本的な使用法
[編集]以下のプログラムは、符号なし右シフト代入演算子の基本的な使用法を示しています。
// 基本的な使用法 let a = -8; let b = 16; let c = 7; a >>>= 2; // -8を2ビット右にシフト b >>>= 3; // 16を3ビット右にシフト c >>>= 1; // 7を1ビット右にシフト console.log(a); // 1073741822 (-8を2ビット右に符号なしシフト) console.log(b); // 2 (16を3ビット右にシフト) console.log(c); // 3 (7を1ビット右にシフト)
このプログラムでは、符号なし右シフト代入演算子(>>>=)を使用して、変数の値を右にシフトして結果を元の変数に代入しています。符号なし右シフトは、ビットを右に移動し、左側に0を埋めます。負の数の場合、符号ビットも0になるため、結果は常に非負整数になります。
符号付き右シフトとの比較
[編集]以下のプログラムは、符号なし右シフト代入演算子(>>>=)と符号付き右シフト代入演算子(>>=)の違いを示しています。
// 符号付き右シフトと符号なし右シフトの比較 let negativeNum1 = -16; let negativeNum2 = -16; let positiveNum1 = 16; let positiveNum2 = 16; // 符号付き右シフト代入 (>>=) negativeNum1 >>= 2; positiveNum1 >>= 2; // 符号なし右シフト代入 (>>>=) negativeNum2 >>>= 2; positiveNum2 >>>= 2; console.log("符号付き右シフト (-16 >>= 2):", negativeNum1); // -4 console.log("符号なし右シフト (-16 >>>= 2):", negativeNum2); // 1073741820 console.log("符号付き右シフト (16 >>= 2):", positiveNum1); // 4 console.log("符号なし右シフト (16 >>>= 2):", positiveNum2); // 4
このプログラムでは、2つの右シフト代入演算子の動作の違いを比較しています:
正の数に対しては、両方の演算子は同じ結果を生成します。
ビット操作のテクニック
[編集]以下のプログラムは、符号なし右シフト代入演算子を使用したビット操作のテクニックを示しています。
// ビット操作のテクニック let color = 0xFF8040; // RGB色:赤(FF)、緑(80)、青(40) // 各色成分を抽出 let red = color; let green = color; let blue = color; // 赤成分のみを取得(上位8ビット) red >>>= 16; // 緑成分のみを取得(中間8ビット) green >>>= 8; green &= 0xFF; // 下位8ビットのみを保持 // 青成分のみを取得(下位8ビット) blue &= 0xFF; console.log("赤:", red.toString(16)); // "ff" console.log("緑:", green.toString(16)); // "80" console.log("青:", blue.toString(16)); // "40" // 色の明るさを半分にする color >>>= 1; // 各色成分を1ビット右にシフト console.log("明るさを半分にした色:", color.toString(16)); // "7fc020"
このプログラムでは、符号なし右シフト代入演算子を使用して、RGB色の各成分を抽出したり、色の明るさを調整したりしています。ビット演算は、グラフィックス処理や最適化が必要なコードで効率的なテクニックとして使用されます。
フラグとの組み合わせ
[編集]以下のプログラムは、フラグ操作における符号なし右シフト代入演算子の使用例を示しています。
// フラグ操作の例 // ビットフラグの定義 const FLAG_READ = 4; // 2^2 = 4 (ビット位置: 2) const FLAG_WRITE = 2; // 2^1 = 2 (ビット位置: 1) const FLAG_EXECUTE = 1; // 2^0 = 1 (ビット位置: 0) // 初期権限セット(読み取りと書き込み権限) let permissions = FLAG_READ | FLAG_WRITE; // 6 console.log("初期権限:", permissions.toString(2)); // "110" // フラグをチェックする関数 function hasPermission(permSet, flag) { return (permSet & flag) !== 0; } console.log("読み取り権限:", hasPermission(permissions, FLAG_READ)); // true console.log("書き込み権限:", hasPermission(permissions, FLAG_WRITE)); // true console.log("実行権限:", hasPermission(permissions, FLAG_EXECUTE)); // false // 権限を1ビット右にシフト(各権限を「1つ下の権限」に変更) permissions >>>= 1; console.log("シフト後の権限:", permissions.toString(2)); // "11" console.log("シフト後の読み取り権限:", hasPermission(permissions, FLAG_READ)); // false console.log("シフト後の書き込み権限:", hasPermission(permissions, FLAG_WRITE)); // true console.log("シフト後の実行権限:", hasPermission(permissions, FLAG_EXECUTE)); // true
このプログラムでは、ビットフラグを使用して権限を表現し、符号なし右シフト代入演算子を使用して権限セットを変更しています。ビットシフトにより、高位のフラグが低位に移動します。
注意点
[編集]- 32ビット整数: JavaScriptでのビット演算は32ビット整数に対して行われます。すべての数値は演算の前に32ビット整数に変換され、結果も32ビット整数として返されます。
- シフト量: 右辺の値(シフト量)は32で割った余りが実際のシフト量になります。つまり、
a >>>= 32はa >>>= 0と同じ結果になります。 - 非数値オペランド: 左辺の値が数値でない場合、演算の前に数値に変換されます。右辺も同様に数値に変換されます。
- NaNとInfinity:
NaNやInfinityなどの特殊な数値を含む演算の結果は予測が難しい場合があります。 - 浮動小数点: 浮動小数点数に対してビット演算を行う場合、まず32ビット整数に変換されることに注意してください。