私はビット単位演算子を使用する理由がなかったと言わなければなりませんが、私はそれらでより効率的に行われたであろう私が実行したいくつかの操作があると確信しています。 「シフト」と「OR-ing」は、問題をより効率的に解決するのにどのように役立ちましたか?
有名な Bit Twiddling Hacks を参照してください
乗算/除算のほとんどは不要です-コンパイラが自動的にそれを行い、ユーザーを混乱させるだけです。
ただし、ハードウェアまたは通信プロトコルを使用する場合に非常に役立つ「チェック/セット/トグルビットN」タイプのハックが多数あります。
文字を小文字に変換します:
OR
by space => _(x | ' ')
_('a' | ' ') => 'a'
_; _('A' | ' ') => 'a'
_文字を大文字に変換します:
AND
下線で=> _(x & '_')
_('a' & '_') => 'A'
_; _('A' & '_') => 'A'
_反転手紙の場合:
XOR
スペースで== _(x ^ ' ')
_('a' ^ ' ') => 'A'
_; _('A' ^ ' ') => 'a'
_アルファベットの位置:
AND
by chr(31)
/binary('11111')
/(hex('1F')
=> _(x & "\x1F")
_('a' & "\x1F") => 1
_; _('B' & "\x1F") => 2
_文字の位置をアルファベットで取得します(大文字文字のみ):
AND
by _?
_ => _(x & '?')
_orXOR
by _@
_ => _(x ^ '@')
_('C' & '?') => 3
_; _('Z' ^ '@') => 26
_文字のpositionをアルファベットで取得(小文字文字のみ):
XOR
backtick/chr(96)
/binary('1100000')
/hex('60')
=> _(x ^ '`')
_('d' ^ '`') => 4
_; _('x' ^ '`') => 25
_注:英語以外の文字を使用すると、ガベージ結果が生成されます
最大整数を取得
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;
2のm乗で除算
n >> m;
奇数を確認
(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;
if(x == a)x = b; if(x == b)x = a;
x = a ^ b ^ x;
どの周波数でもこれまでに使用したことがあるのは3つだけです。
ビットを設定します。a| = 1 <<ビット。
ビットをクリアします:&=〜(1 <<ビット);
ビットが設定されていることをテストします:&(1 <<ビット);
Matters Computational:Ideas、Algorithms、Source Code、by Jorg Arndt(PDF) 。この本にはたくさんのものが含まれています。 http://www.hackersdelight.org/ のリンクから見つけました。
オーバーフローなしの平均
2つの引数xとyの平均(x + y)/ 2を計算するルーチンは次のとおりです。
static inline ulong average(ulong x, ulong y) // Return floor( (x+y)/2 ) // Use: x+y == ((x&y)<<1) + (x^y) // that is: sum == carries + sum_without_carries { return (x & y) + ((x ^ y) >> 1); }
データを圧縮できます。整数のコレクション:
セットビットのカウント、最低/最高セットビットの発見、上から/下のセットビットの発見、その他は有用であり、 bit-twiddling hacks サイトを見る価値があります。
そうは言っても、この種のことは日常的には重要ではありません。ライブラリがあると便利ですが、それでも最も一般的な用途は間接的です(ビットセットコンテナを使用するなど)。また、理想的には、これらは標準のライブラリ関数になります-それらの多くは、一部のプラットフォームで特殊なCPU命令を使用してより適切に処理されます。
1)2の累乗で除算/乗算する
foo >>= x;
(2の累乗で除算)
foo <<= x;
(2のべき乗)
2)スワップ
x ^= y;
y = x ^ y;
x ^= y;
シフトによる乗算/除算は気の利いたようですが、たまに必要なのはブール値をビットに圧縮することだけでした。そのためには、ビット単位のAND/ORと、おそらくビットシフト/反転が必要です。
数値を次に高い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)
ディレクティブをコードに振りかけます。