ビット単位の演算と、それらがさまざまな目的(たとえば、アクセス許可)にどのように役立つかを理解しています。しかし、ビットシフト演算子が何を使用しているのか理解していないようです。それらがどのように機能するかは理解していますが、本当に迅速な乗算または除算を実行したい場合を除いて、それらを使用したいシナリオは考えられません。ビットシフトを使用する他の理由はありますか?
4 に答える
多くの理由があります、ここにいくつかあります:
- 白黒画像をビットのシーケンスとして表現し、この画像に1つのピクセルを一般的に設定するとします。たとえば、バイトオフセットはx >> 3であり、ビットオフセットはx&0x7であり、そのビットを次のように設定できます。(1 <<(x&0x7));
- ハフマン符号化など、可変長ビットシーケンスを処理するデータ圧縮アルゴリズムの実装。
- シリアル通信デバイスなどのハードウェアを操作しているため、いくつかの制御ビットを読み取るか設定する必要があります。
これらおよびその他の理由により、ほとんどのプロセッサには、ビットシフトおよび/またはローテーション命令とその他の論理命令(および/または/ xor / not)があります。
歴史的に、乗算と除算はより複雑な操作であり、一部のCPUにはそれらがまったくないため、大幅に遅くなりました。
こちらもご覧ください: 実際のプロジェクトでビットシフトを使用する必要があったことはありますか?
ご指摘のとおり、左シフトは2を掛けたものと同じです。少なくとも、署名されていない数量について話しているときです。署名された数量の「左シフト」の意味は...言語に依存します。
最近のコンパイラでは、「i = x*2;」と書くことに違いはありません。および「i=x<<1;」コンパイラは最も効率的なコードを生成します。したがって、その意味では、乗算よりもシフトを優先する理由はありません。
一部のアルゴリズムは、数量を1ビット左にシフトしてから、下位ビットを0または1に設定することで機能します。一部の単純な圧縮アルゴリズムは、このように機能します。たとえば、累積値が変数xにあり、現在の値(0または1)がyにある場合、「x」ではなく「x =(x << 1)|y」と書く方が理にかなっています。 =(x * 2)+y"。どちらも同じことをしますが、最初の方が表記上正しいです。「ああ、そうだ、2を掛けるのは左シフトと同じだ」と考える必要はありません。
また、ビットをシフトするアルゴリズムについて話しているときは、2の倍数を乗算または除算するかどうかを判断するよりも、特定のビット数だけ左または右にシフトする方が便利です。
したがって、通常、乗算ではなくシフトによるパフォーマンス上の利点はありませんが(少なくとも高級言語で作業している場合はそうではありません)、シフトする機能があると、実行していることがより簡単に理解できる場合があります。
数値計算での使用以外に、ビットシフト演算が定期的に使用される場所はたくさんあります。たとえば、ビットボードは、ボードゲームでボード表現に一般的に使用されるデータ構造です。最強のチェスエンジンのいくつかは、主に動きの生成と評価の速度と容易さのためにこのデータ構造を使用します。これらのプログラムはビット演算を多用し、ビットシフト演算は特にビットマスクの検索、ボード上での新しい動きの生成、対数の非常に高速な計算など、多くのコンテキストで使用されます。ビット演算を巧みに使用することでエレガントに実行されます。このサイトをチェックしてくださいビットをいじるハックの場合-これらのアルゴリズムの多くはシフト演算子を使用します。ビットシフト操作は、デバイスドライバーのプログラミング、コーデックの開発、組み込みシステムのプログラミングなどで定期的に使用されます。
シフトにより、変数内の特定のビットにアクセスできます。式は、右からビットのオフセットを持つ変数のビット部分を(n >> p) & ((1 << m) - 1)
取得します。m
n
p
これにより、プログラムで8ビットの倍数ではない整数を使用できるようになります。これはデータ圧縮に役立ちます。
たとえば、Netflix Prizeプログラムでこれを使用して、レコード(22ビットのユーザーID +15ビットの映画ID+12ビットの日付+3ビットのレーティング)をuint64_t
(12ビットの余裕を持って)にパックしました。
bool
非常に一般的な特殊なケースは、各バイトに8つの変数をパックすることです。(Unixファイルのアクセス許可、白黒ビットマップ、CPUフラグレジスタなど)
また、ビット操作は、非常に人気のある文字エンコードであるUTF-8で使用されます。Unicode文字は、ビットを1、2、3、または4バイトに分散することによって表されます。