ビット単位の演算子を使用する理由はまったくなかったと言わざるを得ませんが、ビットごとの演算子を使用するとより効率的に実行できたはずの操作がいくつかあると確信しています。「シフト」と「OR-ing」は、問題をより効率的に解決するのにどのように役立ちましたか?
11 に答える
文字列 (文字) に対するビット演算の使用
文字を小文字に変換:
OR
スペースで =>(x | ' ')
- 文字がすでに小文字であっても、結果は常に小文字です
- 例えば。
('a' | ' ') => 'a'
;('A' | ' ') => 'a'
文字を大文字に変換:
AND
下線 =>(x & '_')
- 文字がすでに大文字であっても、結果は常に大文字になります
- 例えば。
('a' & '_') => 'A'
;('A' & '_') => 'A'
文字の大文字と小文字を反転:
XOR
スペースで =>(x ^ ' ')
- 例えば。
('a' ^ ' ') => 'A'
;('A' ^ ' ') => 'a'
アルファベットでの文字の位置:
AND
によってchr(31)
/binary('11111')
/(hex('1F')
=>(x & "\x1F")
- 結果は 1 ~ 26 の範囲で、大文字と小文字は重要ではありません
- 例えば。
('a' & "\x1F") => 1
;('B' & "\x1F") => 2
アルファベットで文字の位置を取得します (大文字のみ):
AND
?
=>(x & '?')
またはXOR
=@
>によって(x ^ '@')
- 例えば。
('C' & '?') => 3
;('Z' ^ '@') => 26
アルファベットで文字の位置を取得します (小文字のみ):
XOR
バッククォートで/chr(96)
/binary('1100000')
/hex('60')
=>(x ^ '`')
- 例えば。
('d' ^ '`') => 4
;('x' ^ '`') => 25
注: 英字以外のものを使用すると、ガベージ結果が生成されます
- 整数のビット演算 (int)
最大整数を取得します
int maxInt = ~(1 << 31);
int maxInt = (1 << 31) - 1;
int maxInt = (1 << -1) - 1;
最小整数を取得します
int minInt = 1 << 31;
int minInt = 1 << -1;
最大の長さを取得します
long maxLong = ((long)1 << 127) - 1;
2倍
n << 1; // n*2
2で割る
n >> 1; // n/2
2のm乗
n << m; // (3<<5) ==>3 * 2^5 ==> 96
2のm乗で割る
n >> m; // (20>>2) ==>(20/( 2^2) ==> 5
奇数チェック
(n & 1) == 1;
2 つの値を交換する
a ^= b;
b ^= a;
a ^= b;
絶対値を取得する
(n ^ (n >> 31)) - (n >> 31);
2 つの値の最大値を取得する
b & ((a-b) >> 31) | a & (~(a-b) >> 31);
2 つの値の最小値を取得する
a & ((a-b) >> 31) | b & (~(a-b) >> 31);
両方が同じ符号を持っているかどうかを確認します
(x ^ y) >= 0;
2^n を計算する
2 << (n-1);
2の階乗かどうか
n > 0 ? (n & (n - 1)) == 0 : false;
m に対するモジュロ 2^n
m & (n - 1);
平均を取る
(x + y) >> 1;
((x ^ y) >> 1) + (x & y);
n の m 番目のビットを取得します (下位から上位へ)
(n >> (m-1)) & 1;
n の m 番目のビットを 0 に設定 (下位から上位へ)
n & ~(1 << (m-1));
n+1
-~n
n - 1
~-n
コントラスト番号を取得する
~n + 1;
(n ^ -1) + 1;
もし (x==a) x=b; もし (x==b) x=a;
x = a ^ b ^ x;
有名なBit Twiddling Hacks
を参照してください。
乗算/除算のほとんどは不要です。コンパイラが自動的に実行するため、人々を混乱させるだけです。
しかし、ハードウェアまたは通信プロトコルを扱う場合に非常に役立つ「チェック/セット/トグル ビット N」タイプのハックがたくさんあります。
私がこれまでに頻繁に使用したことがあるのは 3 つだけです。
少し設定します。
a |= 1 << bit;
少しクリア:
a &= ~(1 << bit);
ビットが設定されていることをテストします。
a & (1 << bit);
1)2の累乗で除算/乗算
foo >>= x;
(2の累乗で割る)
foo <<= x;
(2の累乗を掛ける)
2)スワップ
x ^= y;
y = x ^ y;
x ^= y;
整数のコレクションなど、データを圧縮できます。
- コレクション内でより頻繁に出現する整数値を確認する
- より頻繁に現れる値を表すには短いビット シーケンスを使用します(あまり頻繁に現れない値を表すには長いビット シーケンスを使用します)。
- ビット シーケンスを連結します。たとえば、結果のビット ストリームの最初の 3 ビットは 1 つの整数を表し、次の 9 ビットは別の整数などを表します。
セット ビットのカウント、最小/最大セット ビットの検索、上から n 番目/下のセット ビットの検索などは便利です。
とはいえ、この種のことは日常的に重要ではありません。ライブラリがあると便利ですが、最も一般的な用途は間接的です (例: ビットセット コンテナーを使用)。また、理想的には、これらは標準ライブラリ関数です。それらの多くは、一部のプラットフォームで特化した CPU 命令を使用して処理する方が適切です。
数値を次に高い 2 のべき乗に丸める関数が必要だったので、何度か取り上げられている Bit Twiddling の Web サイトにアクセスして、次のように思いつきました。
i--;
i |= i >> 1;
i |= i >> 2;
i |= i >> 4;
i |= i >> 8;
i |= i >> 16;
i++;
タイプで使用していsize_t
ます。おそらく、署名された型ではうまく機能しません。サイズの異なる型のプラットフォームへの移植性が心配な場合は、コード#if SIZE_MAX >= (number)
の適切な場所にディレクティブを散りばめてください。
シフトによる乗算/除算は気の利いたように見えますが、たまに必要だったのはブール値をビットに圧縮することだけでした。そのためには、ビット単位の AND/OR と、おそらくビット シフト/反転が必要です。