ビット演算子とは何ですか?


129

私は楽しみのためにコードを書く人であり、学術的または専門的な設定でそれを深く掘り下げていないので、これらのビット単位の演算子のようなものは本当に私をエスケープします。

私はJavaScriptに関する記事を読んでいましたが、これは明らかにビット単位の操作をサポートしています。私はこの操作が何度も言及されているのを見続けていますが、正確にそれが何であるかを理解しようと読みましたが、まったく理解できないようです。それで、彼らは何ですか?明確な例は素晴らしいでしょう!:D

もう少し質問-ビット演算の実用的なアプリケーションは何ですか?いつ使用しますか?


2
さらに質問が必要な場合は、新しいSO質問を追加して、この質問を参照してください。そうすれば、より良い答えが得られるでしょう。
グレッグ・ヒューギル

回答:


186

これらが有用である理由について誰も触れていないので:

フラグを操作するときは、ビット演算をよく使用します。たとえば、一連のフラグをオペレーションに渡したい場合(たとえば、File.Open()読み取りモードと書き込みモードの両方が有効になっている場合)、それらを単一の値として渡すことができます。これは、ビットセット内の独自のビット(byte、short、int、またはlong)に可能な各フラグを割り当てることによって実現されます。例えば:

 Read: 00000001
Write: 00000010

したがって、読み取りと書き込みを渡したい場合は、(READ | WRITE)を渡し、2つを組み合わせて

00000011

次に、反対側で次のように復号化できます。

if ((flag & Read) != 0) { //...

どのチェック

00000011 &
00000001

戻る

00000001

これは0ではないため、フラグはREADを指定します。

XORを使用して、さまざまなビットを切り替えることができます。フラグを使用して方向入力(上、下、左、右)を指定するときに、これを使用しました。たとえば、スプライトが水平方向に動いていて、それを反転させたい場合:

     Up: 00000001
   Down: 00000010
   Left: 00000100
  Right: 00001000
Current: 00000100

この場合、現在の値と(LEFT | RIGHT)をXORするだけで、LEFTがオフになり、RIGHTがオンになります。

ビットシフトは、いくつかの場合に役立ちます。

x << y

と同じです

x * 2 y

2の累乗をすばやく乗算する必要があるが、1ビットを上位ビットにシフトすることに注意してください。これにより、符号なしでない限り、数値は負になります。さまざまなサイズのデータ​​を処理する場合にも役立ちます。たとえば、4バイトから整数を読み取る場合:

int val = (A << 24) | (B << 16) | (C << 8) | D;

Aが最上位バイト、Dが最下位であると仮定します。それは次のようになります:

A = 01000000
B = 00000101
C = 00101011
D = 11100011
val = 01000000 00000101 00101011 11100011

色はしばしば次のように保存されます(最上位バイトは無視されるか、アルファとして使用されます):

A = 255 = 11111111
R = 21 = 00010101
G = 255 = 11111111
B = 0 = 00000000
Color = 11111111 00010101 11111111 00000000

値を再度見つけるには、ビットを右にシフトして一番下に移動し、残りの上位ビットをマスクします。

Int Alpha = Color >> 24
Int Red = Color >> 16 & 0xFF
Int Green = Color >> 8 & 0xFF
Int Blue = Color & 0xFF

0xFFと同じ11111111です。したがって、基本的に、Redの場合は次のようにします。

Color >> 16 = (filled in 00000000 00000000)11111111 00010101  (removed 11111111 00000000)
00000000 00000000 11111111 00010101 &
00000000 00000000 00000000 11111111 =
00000000 00000000 00000000 00010101 (The original value)

x << nなので、nは2 ^ valueの形式である必要がありますか?
アーメドC

28

他の回答としてリストされているシングルビットの真理値表は、一度に1つまたは2つの入力ビットでのみ機能することに注意してください。次のような整数を使用するとどうなりますか。

int x = 5 & 6;

答えは、各入力のバイナリ展開にあります。

  5 = 0 0 0 0 0 1 0 1
& 6 = 0 0 0 0 0 1 1 0
---------------------
      0 0 0 0 0 1 0 0

各列のビットの各ペアは、「AND」関数を介して実行され、対応する出力ビットが一番下の行に表示されます。したがって、上記の式の答えは4です。CPUは(この例では)各列に1つずつ、8つの個別の「AND」演算を並行して実行しました。

「AHA!」のことを今でも覚えているので、これについて言及します。私が何年も前にこれを知った瞬間。


うわー、それは今でははるかに理にかなっています。見た目よりもずっと複雑に聞こえました。ありがとう。良い答えがたくさんあるので、どちらを正しい答えとして選択すればよいかわかりません。賛成することはできません。おかげ
クリックします

27

ビット演算子は、一度に少しずつ機能する演算子です。

ANDは、両方の入力が1の場合にのみ1になります。

1つ以上の入力が1の場合、ORは1です。

XORは、その入力の1つだけが1の場合にのみ1になります。

NOTは、その入力が0の場合のみ1です。

これらは真理値表として最もよく説明できます。入力の可能性は上と左にあり、結果のビットは2つの入力の交点に表示される4つの値(1つの入力しかないためNOTの場合は2つ)の1つです。

AND|0 1      OR|0 1
---+----    ---+----
  0|0 0       0|0 1
  1|0 1       1|1 1

XOR|0 1     NOT|0 1
---+----    ---+---
  0|0 1        |1 0
  1|1 0

1つの例は、整数の下位4ビットだけが必要な場合、15(バイナリ1111)とANDするので、次のようになります。

    203: 1100 1011
AND  15: 0000 1111
------------------
 IS  11: 0000 1011

16

これらはビット単位の演算子であり、すべてJavaScriptでサポートされています。

  • op1 & op2- AND演算子は2つのビットを比較し、両方のビットが1の場合は1の結果を生成します。それ以外の場合は0を返します。

  • op1 | op2- OR演算子は2つのビットを比較し、ビットが相補的な場合は1の結果を生成します。それ以外の場合は0を返します。

  • op1 ^ op2- EXCLUSIVE-OR演算子は2つのビットを比較し、どちらかのビットが1の場合は1を返し、両方のビットが0または1の場合は0を返します。

  • ~op1 - COMPLEMENT演算子は、オペランドのすべてのビットを反転するために使用されます。

  • op1 << op2 - SHIFT LEFT演算子はビットを左に移動し、左端のビットを破棄し、右端のビットに値0を割り当てます。左に移動するたびに、op1が2倍されます。

  • op1 >> op2 - SHIFT RIGHT演算子はビットを右に移動し、右端のビットを破棄し、左端のビットに値0を割り当てます。それぞれ右に移動すると、op1が半分に分割されます。左端の符号ビットは保持されます。

  • op1 >>> op2- - SHIFT RIGHTZERO FILLオペレータは、右有効半分にOP1を分割する各移動右端ビットを破棄し、割り当て左端は0の値をビット、右にビットを移動させ 左端の符号ビットは破棄されます。


「ビットが相補的である場合」-え?
Andrey Tyukin

それらの一方が1で他方が0である場合、2ビット@AndreyTyukin相補的である
ジェフヒルマン

@JeffHillmanコメントの説明によると、1と1は「相補的」ではありません。次に、なぜ1 | 1を与えるのか、与え1ないの0か、そしてどのように|してと異なるのかは不明です^。数日前にこのQ / Aを重複ターゲットとして使用する必要があり、10年後にはこの種の質問に対してより明確な正規の重複があることを望みました。
Andrey Tyukin、

4

もう少し細かく分析するには、問題の値のバイナリ表現に大きく関係しています。

例(10進数):
x = 8
y = 1

(バイナリで)出てきます:
x = 1000
y = 0001

そこから、「and」や「or」などの計算操作を実行できます。この場合:
x | y =
1000 
0001 |
------
1001

または... 10進数で9

お役に立てれば。


|OR演算ですか?
Si8 2016

どういうわけか、これは私にとって最も理にかなっています。しかし、そのx | y = 1000 0001 |部分についてはまだ
わかり

4

「ビット単位」という用語が言及されている場合、それが「論理」演算子ではないことを明確にすることがあります。

たとえばJavaScriptでは、ビットごとの演算子はオペランドを32ビットのシーケンス(0と1)として扱います。一方、論理演算子は通常、ブール(論理)値で使用されますが、非ブール型でも機能します。

たとえば、expr1 && expr2を考えます。

falseに変換できる場合はexpr1を返します。それ以外の場合は、expr2を返します。したがって、ブール値とともに使用すると、両方のオペランドがtrueの場合、&&はtrueを返します。それ以外の場合はfalseを返します。

a = "Cat" && "Dog"     // t && t returns Dog
a = 2 && 4     // t && t returns 4

他の人が指摘したように、2&4はビット単位のANDであるため、0を返します。

以下をtest.htmlまたは何かにコピーしてテストできます。

<html>
<body>
<script>
    alert("\"Cat\" && \"Dog\" = " + ("Cat" && "Dog") + "\n"
        + "2 && 4 = " + (2 && 4) + "\n"
        + "2 & 4 = " + (2 & 4));
</script>

3

デジタルコンピュータプログラミングでは、ビット単位の演算は、個々のビットのレベルで1つ以上のビットパターンまたは2進数に作用します。これは、プロセッサによって直接サポートされる高速のプリミティブアクションであり、比較や計算のために値を操作するために使用されます。

オペレーション

  • ビットごとのAND

  • ビットごとのOR

  • ビットごとのNOT

  • ビットごとのXOR

リストアイテム

    AND|0 1        OR|0 1 
    ---+----      ---+---- 
      0|0 0         0|0 1 
      1|0 1         1|1 1 

   XOR|0 1        NOT|0 1 
   ---+----       ---+--- 
     0|0 1           |1 0 
     1|1 0

例えば。

    203: 1100 1011
AND  15: 0000 1111
------------------
  =  11: 0000 1011

ビット演算子の使用

  • 左シフト演算子と右シフト演算子は、それぞれx * 2 yによる乗算と除算と同等です。

例えば。

int main()
{
     int x = 19;
     printf ("x << 1 = %d\n" , x <<1);
     printf ("x >> 1 = %d\n", x >>1);
     return 0;
}
// Output: 38 9
  • &演算子を使用すると、数値が奇数か偶数かをすばやく確認できます

例えば。

int main()
{
    int x = 19;
    (x & 1)? printf("Odd"): printf("Even");
    return 0;
 }
// Output: Odd
  • if elseステートメントなしでxとyの最小値をすばやく見つける

例えば。

int min(int x, int y)
{
    return y ^ ((x ^ y) & - (x < y))
}
  • 10進数から2進数への変換

例えば。

#include <stdio.h>
int main ()
{
    int n , c , k ;
    printf("Enter an integer in decimal number system\n " ) ;
    scanf( "%d" , & n );
    printf("%d in binary number
    system is: \n " , n ) ;
    for ( c = 31; c >= 0 ; c -- )
    {
         k = n >> c ;
         if ( k & 1 )
              printf("1" ) ;
         else
              printf("0" ) ;
      }
      printf(" \n " );
      return 0 ;
}
  • XORゲート暗号化は、プログラマーが複雑で使いやすいため、一般的な手法です。
  • ビットごとのXOR演算子は、技術面接の観点から最も有用な演算子です。

ビット単位のシフトは+ ve番号でのみ機能します

また、ビット単位のロジックの幅広い用途があります


「複雑さと再成長...」?
ジョナサンクロス

The left-shift and right-shift operators are equivalent to multiplication and division by x * 2y respectively.そのとおり! muyiy.cn/question/program/102.html
xgqfrms

私の解決策のrepl.it/@xgqfrms/...
xgqfrms

1

このように考えると役立つかもしれません。これがAND(&)の仕組みです。

基本的には、これらの数値は両方とも1なので、5と3の数値が2つある場合、それらはバイナリに変換され、コンピュータは

         5: 00000101
         3: 00000011

両方とも1です:00000001 0はfalse、1はtrueです

したがって、5と3のANDは1です。OR(|)演算子は同じことを行いますが、1ではなく1である必要があります。両方ではありません。


-5

JavaScriptのビット単位演算子がいかに遅いかについて、私は聞き続けました。私は私の最新のブログ投稿に対していくつかのテストを行ったところ、いくつかのテストで算術計算よりも40〜80%高速であることがわかりました。おそらく、以前は遅いものでした。最近のブラウザーでは、私はそれらを愛しています。

私のコードには、このために速くて読みやすいケースが1つあります。もっと目を開いておくつもりです。

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