web-dev-qa-db-ja.com

ビット単位演算子の実際の使用例

次のビット演算子の実際の使用例は何ですか?

  • そして
  • XOR
  • ない
  • OR
212
Olivier Lalonde
  • ビットフィールド(フラグ)
    これらは、複数の「yesまたはno」プロパティによって状態が定義されているものを表す最も効率的な方法です。 ACLは良い例です。 4つの個別のアクセス許可(読み取り、書き込み、実行、ポリシーの変更)がある場合、4を無駄にするのではなく1バイトに保存することをお勧めします。これらは、利便性を高めるために多くの言語の列挙型にマップできます。

  • ポート/ソケットを介した通信
    常にチェックサム、パリティ、ストップビット、フロー制御アルゴリズムなどが含まれます。これらは通常、数値ではなく個々のバイトの論理値に依存します。時間。

  • 圧縮、暗号化
    これらの両方は、ビット単位のアルゴリズムに大きく依存しています。例として deflate アルゴリズムを見てください-すべてはバイトではなくビットです。

  • 有限状態マシン
    私は主にいくつかのハードウェアに埋め込まれている種類のことを言っていますが、それらはソフトウェアにもあります。これらは本質的に組み合わせです。文字通り「コンパイル」されて論理ゲートの束になることがあるため、ANDORNOTなどとして表現する必要があります。

  • グラフィックスこれらの演算子がグラフィックスプログラミングで使用されるすべての領域に入るための十分なスペースはありません。 XOR(または^)は、同じ入力を2回適用すると最初の入力が元に戻されるため、特に興味深いものです。コストのかかる再描画の必要性を排除するために、選択の強調表示やその他のオーバーレイをこれに依存していた古いGUI。低速のグラフィックプロトコル(リモートデスクトップなど)でも引き続き有用です。

これらは、私が思いついた最初の数例に過ぎません-これは完全なリストではありません。

204
Aaronaught

奇妙ですか?

(value & 0x1) > 0

2(偶数)で割り切れますか?

(value & 0x1) == 0
44
Seth

低レベルのプログラミングが良い例です。たとえば、メモリマップドレジスタに特定のビットを書き込んで、ハードウェアの一部に必要な処理を実行させる必要がある場合があります。

volatile uint32_t *register = (volatile uint32_t *)0x87000000;
uint32_t          value;
uint32_t          set_bit   = 0x00010000;
uint32_t          clear_bit = 0x00001000;

value = *register;            // get current value from the register
value = value & ~clear_bit;   // clear a bit
value = value | set_bit;      // set a bit
*register = value;            // write it back to the register

また、htonl()およびhtons()は、&および|演算子を使用して実装されます( エンディアンネス (バイト順)がネットワークと一致しないマシン上)注文):

#define htons(a) ((((a) & 0xff00) >> 8) | \
                  (((a) & 0x00ff) << 8))

#define htonl(a) ((((a) & 0xff000000) >> 24) | \
                  (((a) & 0x00ff0000) >>  8) | \
                  (((a) & 0x0000ff00) <<  8) | \
                  (((a) & 0x000000ff) << 24))
24
Carl Norum

個別のビットとして保存されたフラグを扱う一般的なイディオムを次に示します。

enum CDRIndicators {
  Local = 1 << 0,
  External = 1 << 1,
  CallerIDMissing = 1 << 2,
  Chargeable = 1 << 3
};

unsigned int flags = 0;

チャージ可能フラグを設定します。

flags |= Chargeable;

CallerIDMissingフラグをクリアします。

flags &= ~CallerIDMissing;

CallerIDMissingおよびChargeableが設定されているかどうかをテストします。

if((flags & (CallerIDMissing | Chargeable )) == (CallerIDMissing | Chargeable)) {

}
24
nos

CMSのセキュリティモデルの実装には、ビット単位の操作を使用しました。ユーザーが適切なグループに属していれば、ユーザーがアクセスできるページがありました。ユーザーは複数のグループに属している可能性があるため、ユーザーグループとページグループの間に交差点があるかどうかを確認する必要がありました。そこで、各グループに一意の2のべき乗の識別子を割り当てました。例:

Group A = 1 --> 00000001
Group B = 2 --> 00000010
Group C = 3 --> 00000100

これらの値をOR一緒に使用し、値を(単一のintとして)ページに保存します。例えば。グループAおよびBがページにアクセスできる場合、ページアクセス制御として値3(バイナリでは00000011)を格納します。ほとんど同じ方法で、ユーザーがどのグループに属しているかを表すために、ユーザーにORされたグループ識別子の値を保存します。

そのため、特定のユーザーが特定のページにアクセスできるかどうかを確認するには、値をANDして、値がゼロ以外であるかどうかを確認するだけです。このチェックは単一の命令で実行され、ループもデータベースの往復も行われないため、これは非常に高速です。

22
JonoW

たとえば、それらを使用して、パックされたカラー値からRGB(A)値を取得します。

21
Terje

多数のブールフラグがある場合、それらをすべてintに格納するのが好きです。

ビット単位のANDを使用してそれらを取り出します。例えば:

int flags;
if (flags & 0x10) {
  // Turn this feature on.
}

if (flags & 0x08) {
  // Turn a second feature on.
}

等.

14
James Cronen

&= AND:
特定のビットをマスクします。
表示または非表示する特定のビットを定義しています。 0x0&xはバイト内のすべてのビットをクリアし、0xFFはxを変更しません。 0x0Fは、下位ニブルのビットを表示します。

変換:
。アイデンティティを保持するには、変換後にマスクを適用します。

| = OR
ビットを設定します。既に設定されている場合、ビットは独立して設定されます。多くのデータ構造(ビットフィールド)には、IS_HSET = 0、IS_VSET = 1などのフラグがあり、これらは個別に設定できます。フラグを設定するには、IS_HSET | Apply IS_VSET(Cおよびアセンブリでは、これは非常に便利です)

^ = XOR
同じまたは異なるビットを検索します。

〜= NOT
ビットを反転します。

all可能なローカルビット操作は、これらの操作によって実装できることが示されます。必要に応じて、ビット演算のみでADD命令を実装できます。

素晴らしいハック:

http://www.ugcs.caltech.edu/~wnoise/base2.html
http://www.jjj.de/bitwizardry/bitwizardrypage.html

11
Thorsten S.

暗号化はすべてビット単位の操作です。

11
recursive

データをハッシュするための迅速で汚い方法として使用できます。

int a = 1230123;
int b = 1234555;
int c = 5865683;
int hash = a ^ b ^ c;
9
ChaosPandion

PLCとのシリアル通信のチェックサムを計算するために、約3分前にビット単位のXOR(^)を使用しました...

8
ezod

これは、バイト形式のビットマップ画像から色を読み取る例です

byte imagePixel = 0xCCDDEE; /* Image in RRGGBB format R=Red, G=Green, B=Blue */

//To only have red
byte redColour = imagePixel & 0xFF0000; /*Bitmasking with AND operator */

//Now, we only want red colour
redColour = (redColour >> 24) & 0xFF;  /* This now returns a red colour between 0x00 and 0xFF.

この小さな例がお役に立てば幸いです...

6
Buhake Sindi

ビット単位の&は、バイトの特定の部分をマスク/抽出するために使用されます。

1バイト変数

 01110010
&00001111 Bitmask of 0x0F to find out the lower nibble
 --------
 00000010

特に、シフト演算子(<< >>)が計算によく使用されます。

6
DrDol

今日の現代言語の抽象化された世界では、多すぎません。 File IOは簡単に思い浮かびますが、それは既に実装されているものに対してビット単位の操作を実行しており、ビット単位の操作を使用するものを実装していません。それでも、簡単な例として、このコードはc#でファイルの読み取り専用属性を削除する方法を示しています(FileMode.Createを指定する新しいFileStreamで使用できるように)。

//Hidden files posses some extra attibutes that make the FileStream throw an exception
//even with FileMode.Create (if exists -> overwrite) so delete it and don't worry about it!
if(File.Exists(targetName))
{
    FileAttributes attributes = File.GetAttributes(targetName);

    if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
        File.SetAttributes(targetName, attributes & (~FileAttributes.ReadOnly));

    File.Delete(targetName);
}

カスタム実装に関しては、最近の例です:分散アプリケーションのインストールから別のインストールに安全なメッセージを送信するための「メッセージセンター」を作成しました。基本的に、受信トレイ、送信トレイ、送信済みなどを備えた電子メールに似ていますが、開封確認付きの配信も保証されているため、「受信トレイ」と「送信済み」以外のサブフォルダーがあります。これは、「受信トレイにあるもの」または「送信済みフォルダーにあるもの」を一般的に定義するための要件でした。送信されたフォルダのうち、何が読まれ、何が未読かを知る必要があります。未読のもののうち、受け取ったものと受け取っていないものを知る必要があります。この情報を使用して、ローカルデータソースをフィルタリングし、適切な情報を表示する動的where句を作成します。

列挙型の組み立て方法は次のとおりです。

    public enum MemoView :int
    {
        InboundMemos = 1,                   //     0000 0001
        InboundMemosForMyOrders = 3,        //     0000 0011
        SentMemosAll = 16,                  //     0001 0000
        SentMemosNotReceived = 48,          //     0011
        SentMemosReceivedNotRead = 80,      //     0101
        SentMemosRead = 144,                //     1001
        Outbox = 272,                       //0001 0001 0000
        OutBoxErrors = 784                  //0011 0001 0000
    }

これが何をするのかわかりますか? 「Inbox」列挙値であるInboundMemosとのAND(&)により、InboundMemosForMyOrdersが受信ボックスにあることがわかります。

以下は、現在選択されているフォルダーのビューを定義するフィルターを作成して返すメソッドの要約版です。

    private string GetFilterForView(MemoView view, DefaultableBoolean readOnly)
    {
        string filter = string.Empty;
        if((view & MemoView.InboundMemos) == MemoView.InboundMemos)
        {
            filter = "<inbox filter conditions>";

            if((view & MemoView.InboundMemosForMyOrders) == MemoView.InboundMemosForMyOrders)
            {
                filter += "<my memo filter conditions>";
            }
        }
        else if((view & MemoView.SentMemosAll) == MemoView.SentMemosAll)
        {
            //all sent items have originating system = to local
            filter = "<memos leaving current system>";

            if((view & MemoView.Outbox) == MemoView.Outbox)
            {
                ...
            }
            else
            {
                //sent sub folders
                filter += "<all sent items>";

                if((view & MemoView.SentMemosNotReceived) == MemoView.SentMemosNotReceived)
                {
                    if((view & MemoView.SentMemosReceivedNotRead) == MemoView.SentMemosReceivedNotRead)
                    {
                        filter += "<not received and not read conditions>";
                    }
                    else
                        filter += "<received and not read conditions>";
                }
            }
        }

        return filter;
    }

非常に単純ですが、抽象レベルでのきちんとした実装であり、通常はビット単位の操作を必要としません。

5
Fred

Base64エンコーディングは一例です。 Base64エンコーディングは、電子メールシステム(およびその他の目的)で送信するための印刷可能な文字としてバイナリデータを表すために使用されます。 Base64エンコードは、一連の8ビットバイトを6ビット文字ルックアップインデックスに変換します。 Base64エンコードおよびデコードに必要なビット演算を実装するには、ビット演算、シフト、および「ing」または「ing」、「not」の表記が非常に便利です。

もちろん、これは数え切れないほどの例の1つにすぎません。

4
rayd09

インターネット時代の明らかな答えを誰も選ばなかったのには驚いた。サブネットの有効なネットワークアドレスの計算。

http://www.topwebhosts.org/tools/netmask.php

4
Bill

固定小数点演算について言及した人はいないようです。

(ええ、私は古いです、大丈夫ですか?)

3
Jason Williams

通常、ビット単位の演算は、乗算/除算を行うよりも高速です。したがって、変数xに9を掛ける必要がある場合、x<<3 + xを実行します。これはx*9よりも数サイクル高速です。このコードがISR内にある場合、応答時間を節約できます。

同様に、配列を循環キューとして使用する場合は、ビット単位の操作でラップアラウンドチェックを処理する方が高速(かつエレガント)です。 (アレイのサイズは2のべき乗でなければなりません)。たとえば、挿入/削除する場合は、tail = ((tail & MASK) + 1)の代わりにtail = ((tail +1) < size) ? tail+1 : 0を使用できます。

また、エラーフラグに複数のエラーコードをまとめて保持する場合は、各ビットに個別の値を保持できます。それをチェックとして個々のエラーコードとANDすることができます。これはUnixエラーコードで使用されます。

また、nビットのビットマップは、本当にクールでコンパクトなデータ構造になります。サイズnのリソースプールを割り当てる場合、nビットを使用して現在のステータスを表すことができます。

3
user3382203

私はそれらを複数選択オプションに使用し、このように10以上ではなく1つの値のみを保存します

2
SQLMenace

sQLリレーショナルモデルでも便利です。次のテーブルがあるとします。BlogEntry、BlogCategory

従来、BlogEntryCategoryテーブルを使用してそれらの間にnn関係を作成するか、BlogEntryで1つの値を使用して、フラグ付き列挙と同様に複数のBlogCategoryレコードにリンクできるBlogCategoryレコードがほとんどない場合、ほとんどのRDBMSその「フラグ付き」列で選択する非常に高速な演算子...

2
Tim Mahy

マイクロコントローラの出力の一部のビットのみを変更したいが、書き込むレジスタがバイトである場合、次のようなことを行います(擬似コード):

char newOut = OutRegister & 0b00011111 //clear 3 msb's
newOut = newOut | 0b10100000 //write '101' to the 3 msb's
OutRegister = newOut //Update Outputs

もちろん、多くのマイクロコントローラーでは、各ビットを個別に変更できます...

2

数値xは2の累乗ですか? (たとえば、カウンターがインクリメントされ、アクションが対数回数だけ行われるアルゴリズムで有用です)

(x & (x - 1)) == 0

整数xの最上位ビットはどれですか? (たとえば、これはxよりも大きい最小の2のべき乗を見つけるために使用できます)

x |= (x >>  1);
x |= (x >>  2);
x |= (x >>  4);
x |= (x >>  8);
x |= (x >> 16);
return x - (x >>> 1); // ">>>" is unsigned right shift

整数xの最下位1ビットはどれですか? (2で割り切れる回数を見つけるのに役立ちます。)

x & -x
2

数値mod(%)を特定の2の累乗で計算したい場合は、yourNumber & 2^N-1を使用できます。この場合、yourNumber % 2^Nと同じです。

number % 16 = number & 15;
number % 128 = number & 127;

これはおそらく、2 ^ Nの非常に大きな配当を伴うモジュラス演算の代替としてのみ有用です...しかし、それでもモジュラス演算の速度向上は、.NET 2.0での私のテストでは無視できます。現代のコンパイラはすでにこのような最適化を実行していると思われます。誰もこれについてもっと知っていますか?

2
Dan7

ハノイの塔線形ソリューションは、ビット演算を使用して問題を解決します。

public static void linear(char start, char temp, char end, int discs)
{
    int from,to;
    for (int i = 1; i < (1 << discs); i++) {
        from = (i & i-1) % 3;
        to = ((i | i-1) + 1) % 3;
        System.out.println(from+" => "+to);
    }
}

このソリューションの説明は here にあります。

1
Dungeon Hunter

それらは主にビット単位の操作に使用されます(驚き)。 PHPコードベースにある実際の例をいくつか示します。

文字コード:

if (s <= 0 && (c & ~MBFL_WCSPLANE_MASK) == MBFL_WCSPLANE_KOI8R) {

データ構造:

ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK;

データベースドライバー:

dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READONLY);

コンパイラー実装:

opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;
1
Constantin

これはビット単位とは見なされませんが、Rubyの配列は通常の整数ビット単位演算子を使用して集合演算を定義します。だから[1,2,4] & [1,2,3] # => [1,2]a ^ b #=> set differenceおよびa | b #=> unionについても同様です。

1
Tim Snowhite

ロールベースのアクセス制御システムで使用されているのを見てきました。

1
ScottE

最初にCプログラミングを始めたときはいつでも、真理値表とそのすべてを理解していましたが、この記事を読むまで実際に使用する方法についてはクリックしませんでした http://www.gamedev.net/reference/articles /article1563.asp (実際の例を示します)

1
Earlz

ここで私の質問に実際の使用があります-
最初のWM_KEYDOWN通知のみに応答しますか?

Windows C APIビット30でWM_KEYDOWNメッセージを使用する場合、以前のキー状態を指定します。値は、メッセージが送信される前にキーがダウンしている場合は1、キーがアップしている場合はゼロです。

1
Nick Van Brunt

数回のゲーム開発の本で、乗算と除算のより効率的な方法としてそれを見てきました。

2 << 3 == 2 * 8 
32 >> 4 == 32 / 16
0
Seth Reno

まだ誰もコレクションに言及していません。場合によっては、可能な値の小さなコレクション、たとえば10または20の可能な値のみがあり、それらの一部をセットに保持したい場合があります。確かに通常のSet実装を使用できますが、これはおそらくバッキングハッシュテーブルを使用します。しかし、可能な値のセットは非常に小さいため、これは実際には時間とスペースの無駄にすぎません。代わりに、正しく覚えていれば、Java int が行うこととまったく同じ単一のlongまたはEnumSet値にセットを格納できます。

0
wds

高速BCD計算を実装するためにそれらを使用します(会計士と監査人はfp丸めに腹を立てます)。

0
Erik Elmgren

私は常にビット単位の操作は実行するのが非常に簡単な操作であると仮定していました。したがって、実行時間が重要な場合、ビットセットを介して実装されるソリューションは、アルゴリズムに応じて一定量だけ実行時間を改善できます。

0
Jacob Bellamy

Bitwise Flagsを使用して、内部Webサイトでのログイン許可のセッションを小さくします。

0
Dave

一般的な用途はアライメントです。たとえば、データを4バイトまたは16バイトの境界にアライメントする必要があります。これは、アライメントされていないロード/ストアが高価なRISCプロセッサで非常に一般的です位置合わせされていない負荷まで)またはまったく許可されません。

2の累乗であるアライメントの場合、次のアライメントされたposは次のように計算できます。

aligned_offset = alignment + ((current_offset - 1) & ~(alignment - 1))

したがって、4バイトの位置合わせと9の現在のオフセットの場合:

aligned_offset = 4 + ((9-1) & ~(4-1)) = 4 + (8 & 0xFFFFFFFC) = 4+ 8  = 12  

したがって、次の4バイトにアライメントされたオフセットは12になります。

0
zebrabox

オプションの組み合わせを単一の整数に格納するために、ビット演算をよく使用します。

int options = 0;

OPTION1は1、OPTION2は2、OPTION3は4、OPTION4は8、OPTION5は16、...

void addOption(int option)は、|演算子を使用してオプションをオプションに追加します。

boolean hasOption(int option)は、&演算子を使用して、オプション内のオプションをテストします。

0
rayd09

それらをオプションハンドラとして使用します。アクセス制御リストで特定のリソースを説明します。

この記事をご覧ください http://planetozh.com/blog/2006/05/php-bitwise-operators-example-of-use/

もう1つのリンク: http://blog.code-head.com/how-to-write-a-permission-system-using-bits-and-bitwise-operations-in-php

0
takeshin

しばらく前に binary writer/reader を示す小さなwiki記事を書きました。ビットレベルで動作し、ビット演算子を使用してデータをパックする方法を示します。それはおそらくゲームでの用途があるので、「現実世界」の例でしょう。

0
Sirisian

非常に具体的な例ですが、数独ソルバーをより速く実行するためにそれらを使用しました(友人と競争していました)

各列、行、および3x3は符号なし整数として表され、数値を設定すると、関連列、行、および3x3の正方形に設定された数値の適切なビットにフラグを立てます。

これにより、右の列、行、3x3の正方形をORするので、与えられた正方形に配置できる数字を簡単に確認できます。特定のポジションの有効な値。

それが理にかなっていることを願っています。

0
Tom Duckering

データベースの世界におけるもう1つの現実のアプリケーションは、MySQLであり、これは SET と呼ばれるデータ型を持っています。

ビット単位演算子は、DBMSによってSETデータ型を格納します。セットはスペースを節約できます。

Element    SET Value    Decimal Value
Travel      00000001    1
Sports      00000010    2
Dancing    00000100    4
Fine Dining   00001000  8
0
Yada