ビットワイズ演算子の実際の使用例[終了]


224

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

  • そして
  • XOR
  • ない
  • または
  • 左/右シフト

1
私がそれらについて初めて知ったとき、それらは低レベルのcにのみ使用されているように見えたのを覚えています... 今は+と*のようなものです。
Oak

2
@Anon .:私の考えでは、現実世界は、ビット単位演算子の最も明白な使用法である低レベルのプログラミング以外のものを意味するはずでした。
Olivier Lalonde



バイナリXORを使用して置換の欠損数を見つけることもできます:martinkysel.com/codility-permmissingelem-solution
Janac Meena

回答:


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

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

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

  • 有限状態機械
    私は主に、ハードウェアの一部に組み込まれている種類について話していますが、ソフトウェアでも見つけることができます。これらは、自然の中で、組み合わせている-彼らはのように表現する必要があるので、彼らは文字通り、論理ゲートの束を「コンパイル」ダウンを取得される可能性がありますANDORNOT、など

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

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


こんにちは@Aaronaught、あなたは本当に私たちと非常に良い知識を共有しました。ビットワイズオペレーターの実世界のケースについてもっと知りたいです。私たちとあなたの参照を共有していただけませんか、それについてもっと読むと本当に役に立ちます。
Heena Hussain

ビット単位の演算はベクトル化可能な計算に役立ちますか?
アーロンフランケ2018年

47

変ですか?

(value & 0x1) > 0

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

(value & 0x1) == 0

3
言語によっては、&0x1> 0が値&(0x1> 0)として解析される場合があります
leeeroy

3
@leeeroy-十分だ。いくつかの括弧を追加しました。
Seth

最新のオプティマイザは、(value%2)!= 0のような式を上記の式に自動的に変換します。godbolt.org/z/mYEBH4
Ferrarezi

26

以下は、個々のビットとして格納されたフラグを扱う一般的な慣用句です。

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)) {

}

25

CMSのセキュリティモデルの実装にビット演算を使用しました。ユーザーが適切なグループに属している場合、ユーザーがアクセスできるページがありました。ユーザーは複数のグループに属している可能性があるため、ユーザーグループとページグループの間に共通部分があるかどうかを確認する必要がありました。したがって、各グループに一意の2のべき乗の識別子を割り当てました。例:

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

これらの値のORをとり、その値を(単一のintとして)ページに格納します。たとえば、グループAとBがページにアクセスできる場合、ページアクセスコントロールとして値3(バイナリでは00000011)を格納します。同様に、ユーザーとOR結合されたグループ識別子の値を格納して、どのグループに属しているかを表します。

したがって、特定のユーザーが特定のページにアクセスできるかどうかを確認するには、値をAND演算し、値がゼロ以外かどうかを確認するだけです。このチェックは単一の命令で実装されているため、これは非常に高速で、ループもデータベースのラウンドトリップもありません。


24

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

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))

7
誰もが機械で話すわけではありません。あなたの2番目の例は何をしていますか?
ChaosPandion 2010年

7
htons()およびhtonl()は、ホスト()のエンディアンからネットワーク()のバイトオーダーにa shortまたはa を交換するPOSIX関数です。longhn
Carl Norum、2010年

同様の方法を使用して、O(logN)操作でビット反転を行うことができます。
Mike DeSimone、2010年

初めて見た時の笑
0x499602D2 2013年

htonl()32ビットint値ではないですか?long多くの言語で64ビットを意味します。
アーロンフランケ

21

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


そして、それは本当に迅速に行われます!
Callum Rogers

C#では、読みやすさと速度の点で、それが本当に最良のソリューションであるケースの1つです。
CaptainCasey 2010年

4
私のマシンで(a & b) >> cは、a % d / e(ARGBを表すintから単一のカラー値を抽出する両方の方法)よりも5倍以上高速です。それぞれ、10億回の反復で6.7秒と35.2秒。
Benji XVI

@BenjiXVI C#には、このためのコンパイラ最適化があります。速度の違いを観察する理由は、C#では%、剰余演算子ではなく剰余演算子であるためです。これらは正の値と同等ですが、負の値とは異なります。適切な制限を提供する場合(たとえばのuint代わりにintを渡す)、2つの例は同じ速度になります。
アーロンフランケ

すみません、久しぶりです。それらを使用してすべてのRGB値を取得する方法の例を示していただけますか?
Jinx

14

ブールフラグがたくさんあるとき、それらをすべてintに格納するのが好きです。

私はビットごとのANDを使用してそれらを取り出します。例えば:

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

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


23
うまくいけば、それらは実際のコードでは定数であり、マジックナンバーではありません:)
Earlz

1
非低レベルの世界でブールフラグを使用する1つの例は、さまざまなGUIプラットフォームで何かを行うことです。たとえば、my_button.Style | = STYLE_DISABLEDを使用してオフにすることができます。
MauriceL 2010年

1
私はこのトピックが言語にとらわれないことを知っていますが、Cはビットフィールドを使用してこれを行う簡単な方法を提供するので、のようなものを使用できますif (flags.feature_one_is_one) { // turn on feature }。これはANSI C標準に含まれているため、移植性は問題になりません。
ポーランド人2014年

このコードスニペットの機能、フラグが初期化されない理由、「それらをすべてintに保存する」とはどういう意味か、使用されている表記は何
ですか?

12

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

変換:
短い変数をビットIDの長い変数にキャストするには、ビットを調整する必要があります。これは、intの-1が0xFFFFFFFFで、longの-1が0xFFFFFFFFFFFFFFFFだからです。IDを保持するには、変換後にマスクを適用します。

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

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

〜=
フリップビットではありません。

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

いくつかの素晴らしいハック:

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


以下は、AS3でビットごとの演算子を使用して非常に高速な数学演算を行う優れた例を示したリンクです(ただし、ほとんどの言語に適用できる可能性があります):lab.polygonal.de/2007/05/10/bitwise-gems-fast- integer-math
2010年

私が考えるべきである「NOT」= ~ではない、|=あるORいます。
Mike DeSimone

& = AND-なぜ私はすべてのビットをクリアしたいだろう、なぜ私はバイトの無修正バージョンを取得したい、と私は下位ニブルをどうするかだのでしょうか?
confused00

1
@ confused00右、結果を無効にするより速く/より簡単な方法は、xorそれ自体です。私はあなたがより低いニブルを抽出したくなるかもしれないかなりの数の理由を考えることができます。特に、その下位ニブルがデータ構造の一部であり、それをマスクとして、またはOR別の構造体で使用したい場合。
James M. Lay

11

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


4
本当に?暗号化の実装ではビット単位の演算が使用される可能性がありますが、暗号化アルゴリズムは通常、ビット表現ではなく数値で記述されます。
コンスタンティン

1
それでは、それらを実装する以外のアルゴリズムをどのように使用しますか?私は興味がある。
再帰的

2
@Constantin:参照、例えば、DESの実装方法の説明:(en.wikipedia.org/wiki/...
ウェインコンラッド

1
@recursive、個人的に私について質問している場合-私は暗号アルゴリズムを設計したり実装したりしていません。しかし、人々は理論的な弱点を分析するなど、多くのことをします。
コンスタンティン

@Constantin:これを見て、これは、暗号化アルゴリズムは、典型的には記載されている方法(の一部)には多くの中ほんの一例である: en.wikipedia.org/wiki/Substitution_box
SyntaxT3rr0r

9

データをハッシュするための迅速でダーティーな方法としてそれらを使用できます。

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

8

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


7

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

1バイト変数

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

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


6

これは、ビットマップイメージからバイト形式で色を読み取る例です。

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.

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


5

今日の現代言語の抽象化された世界では、多すぎません。ファイル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);
}

カスタム実装に関する限り、これが最近の例です。私は、分散アプリケーションの1つのインストールから別のインストールに安全なメッセージを送信するための「メッセージセンター」を作成しました。基本的には、メールに似ており、受信トレイ、送信トレイ、送信済みなどが揃っていますが、開封済みメッセージの配信も保証されているため、「受信トレイ」と「送信済み」以外の追加のサブフォルダがあります。これは、「受信トレイ内」や「送信済みフォルダ内」を一般的に定義するための要件でした。送信したフォルダのうち、何を読んだか、何を読んでいないかを知る必要があります。未読のもののうち、何が受信され、何が受信されていないかを知る必要があります。この情報を使用して、ローカルデータソースをフィルタリングし、適切な情報を表示する動的な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と(&)をアンディングすることで、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;
    }

非常に単純ですが、通常はビット単位の演算を必要としない抽象化レベルでのきちんとした実装です。


4

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

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



4

通常、ビット単位の演算は、乗算/除算を行うよりも高速です。したがって、変数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

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

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

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

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

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

x & -x

符号なし右シフトは、CでLHSを符号なし型にキャストすることによって行われます。最後の式では、最下位の[セット]ビットが見つかりません。Xが2の累乗であるかどうかが確認されますx & -x。最下位のセットビットを見つけるには、を実行します。
Potatoswatter 2010年

うーん、あなたは正しいです、どういうわけか私はx&-xを最初のスニペット、thxを編集用に置き換えました
Dimitris Andreou

3

ビットワイズ演算子は、長さが2のべき乗である配列のループに役立ちます。多くの人が述べたように、ビットワイズ演算子は非常に便利で、フラググラフィックスネットワーク暗号化で使用されます。それだけでなく、非常に高速です。私の個人的なお気に入りの使用法は、条件なしで配列ループすることです。あなたが持っていると仮定し、ゼロ・インデックスベースの配列を(例えば最初の要素のインデックスは0である)、あなたはそれ無限にループする必要があります。無期限に、私は最初の要素から最後に行き、最初に戻ることを意味します。これを実装する1つの方法は次のとおりです。

int[] arr = new int[8];
int i = 0;
while (true) {
    print(arr[i]);
    i = i + 1;
    if (i >= arr.length) 
        i = 0;
}

これは最も単純なアプローチです。if ステートメントを避けたい場合は、次のように係数アプローチを使用できます。

int[] arr = new int[8];
int i = 0;
while (true) {
    print(arr[i]);
    i = i + 1;
    i = i % arr.length;
}

これらの2つの方法の欠点は、整数の除算後に剰余を探すため、モジュラス演算子が高価になることです。そして、最初のメソッドは各反復でifステートメントを実行します。ただし、ビット単位演算子を使用すると、配列の長さが2の累乗の場合、(ビット単位AND)演算子0 .. length - 1を使用するなどの方法でシーケンスを簡単に生成できます。これを知っていると、上からのコードは&i & length

int[] arr = new int[8];
int i = 0;
while (true){
    print(arr[i]);
    i = i + 1;
    i = i & (arr.length - 1);
}

これがどのように機能するかです。バイナリフォーマット1減算2の累乗であるすべての数は唯一のもので表されます。たとえば、バイナリの3は11、7は111、15は以下の1111ようになります。ここで、&バイナリの1のみで構成される数値に対して数値を入力するとどうなりますか?これを行うとしましょう:

num & 7;

場合numより小さい又は7に等しく、その結果はとなりnum、各ビットがので&1と-ed自体です。numが7より大きい場合、&操作中、コンピューターは7の先行ゼロを考慮します。もちろん、&操作後はゼロとして残り、後続部分のみが残ります。9 & 7バイナリの場合のように、それは次のようになります

1001 & 0111

結果は0001になります。これは10進数で1で、配列の2番目の要素をアドレス指定します。


配列の長さが2の累乗である場合、テキストの途中でコメントを最初の文に挿入する必要があります。このトリックを使用することは非常に深刻な制限です。個人的にはとにかくこれを実装しません、コードはifまたはmodアプローチよりも理解するのが難しいです。
Jan Doggen、

@JanDoggenそうです、私は最初の文にそれを入れます。アレイが2の累乗であることについては、私の経験では、それが機能するときは数回以上ありました。おそらくネットワークとグラフィックスに関連していたからでしょう。
user3552161 2016年

1
この投稿の要点は、ビットごとの演算子が数値のシーケンスを生成するのに役立つことを示すことでした。
user3552161 2016年

2

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


2

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

伝統的に、BlogEntryCategoryテーブルを使用してそれらの間にnn関係を作成できます。または、BlogCategoryレコードがそれほど多くない場合、フラグ付き列挙型と同じように、BlogEntryの1つの値を使用して複数のBlogCategoryレコードにリンクできます。ほとんどのRDBMSにもその「フラグ付き」列で選択する非常に高速な演算子...


2

マイクロコントローラーの出力の一部のビットのみを変更したいが、書き込むレジスタがバイトの場合は、次のようにします(疑似コード)。

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

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


これは何語でしょうか?
カーソンマイヤーズ

@Carson:言語はありません。これは疑似コードです。私は実際には数年前、それは国会だったが、私はそれがCで頭をありがとうそれを行うのは簡単です、私はそれをより明確にするために更新されますと仮定していることをやったときに
エミリオM Bumachar

回答を編集してコメントを変更したので、ハイライト表示があまり変更されませんでした。そして、私はそれがCかもしれないと思ったが、あなたは0bを使用した... C で利用可能であると望む記法
Carson Myers

2

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

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

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


コンパイラは、この最適化を使用するのです...しかし、あなたは、最適化について知らなかった場合は、2の正確なパワーだ除数迎えに失敗する可能性があります
ベンフォークト

状況によります。C#では、これは実際にはさまざまな結果を生成します%。Remainder操作と同様に、これらは否定を異なる方法で処理します。ただし、に渡すuint%、2番目の引数が既知の2の累乗である場合、C#コンパイラは実際にはビットごとのANDを使用してマシンコードを生成します。
アーロンフランケ2018年

1

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



1

これらは主にビット単位の演算(サプライズ)に使用されます。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

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


1
いいえ、同じではありません。Cでは、場合x == 1y == 2、その後、x || y1と評価され、x | y評価さ0にも、なぜ私は見ていますかx^trueに優れている!x任意の方法インチ それはタイピングが多く、慣用的でxはなく、偶然ではない場合はbool信頼できません。
David Thornley、2010年

ちょっと待って..ええ、それは私の側ではばかげています。今日はまっすぐに考えることができないようです。
Earlz '19年

x | yは3と評価されます(編集:nvm、編集されたものを参照しているようです!)
ポッド

1
@DavidThornley:x^trueより優れているの!xsome->complicated().member->lookup ^= true; 、単項演算子の複合代入バージョンがない場合です。
Ben Voigt 2013年

1

これはビット単位とは見なされませんが、Rubyの配列は通常の整数ビット単位演算子を介して集合演算を定義します。ですから[1,2,4] & [1,2,3] # => [1,2]。同様のためa ^ b #=> set differencea | b #=> union


1

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

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);
    }
}

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.