今日のレッスンでは、Java ビット単位演算子について理解し、それらを使用する方法の例を検討します。「ビット」という言葉はご存知かと思います。そうでない場合は、その意味を思い出してください :) ビットは、コンピュータ内の情報の最小単位です。その名前は
2 進数に由来します。ビットは、1 または 0 の 2 つの数値のいずれかで表現できます。1 と 0 に基づく特別な 2 進数体系があります。ここでは数学的なジャングルには立ち入りません。Java の任意の数値はバイナリ形式に変換できることだけに注意してください。これを行うには、ラッパー クラスを使用する必要があります。
たとえば、 intに対してこれを行う方法は次のとおりです。
public class Main {
public static void main(String[] args) {
int x = 342;
System.out.println(Integer.toBinaryString(x));
}
}
コンソール出力:
101010110 1010 10110 (読みやすくするためにスペースを追加しました) は、10 進数の数値 342 です。実際には、この数値を 0 と 1 の個々のビットに分解しました。ビットに対して実行される演算は、
ビットごとと呼ばれます。
この演算子は非常に単純です。数値の各ビットを渡し、ビットを反転します。0 は 1 になり、1 は 0 になります。これを数値 342 に適用すると、次のようになります。
101010110 は、2 進数で表される 342 です。 010101001 は、式 ~342 の値です。 これを実践してみましょう。
public class Main {
public static void main(String[] args) {
int x = 342;
System.out.println(~x);
}
}
コンソール出力:
169 169 は、おなじみの 10 進法での 結果 (
010101001 ) です:)
ご覧のとおり、これは論理 AND (
&& ) と非常によく似ています。
&&演算子は、両方のオペランドが true の場合にのみ true を返します。ビットごとの
& も同様の方法で動作し、2 つの数値をビットごとに比較します。比較により 3 番目の数値が生成されます。たとえば、数値 277 と 432 を考えてみましょう。
110110000 は 277 を 2 進数で表します。 1000101011 は 432 を 2 進数で表します。 次に、演算子
& は、上の数値の最初のビットを下の数値の最初のビットと比較します。これは AND 演算子であるため、両方のビットが 1 の場合にのみ結果が 1 になります。それ以外の場合、結果は 0 になります。 100010101
&&演算子 まず、2 つの数値の最初のビットを比較し、次に 2 番目のビット、次に 3 番目のビットを比較します。ご覧のとおり、数値内の対応するビットが両方とも 1 に等しいケースは 2 つだけです (最初のビットと 5 番目のビット)。他のすべての比較では 0 が生成されました。最終的に、数値 10001000 が得られました。10 進法では、数値 272 に対応します。確認してみましょう。
public class Main {
public static void main(String[] args) {
System.out.println(277&432);
}
}
コンソール出力:
272
この演算子は同じように機能し、2 つの数値をビットごとに比較します。ここでのみ、ビットの少なくとも 1 つが 1 の場合、結果は 1 になります。同じ数値 (277 と 432) を見てみましょう
。110110000 _______________ 110110101 - | の結果 演算子 ここでは、異なる結果が得られます。ゼロのまま残るビットは、両方の数値でゼロだったビットだけです。結果は、数値 110110101 です。10 進数では、数値 437 に対応します。確認してみましょう。
public class Main {
public static void main(String[] args) {
System.out.println(277|432);
}
}
コンソール出力:
437 すべて正しく計算されました。:)
この演算子にはまだ出会っていません。しかし、それについては何も複雑なことはありません。これは通常の OR 演算子と似ています。違いが 1 つあります。通常の OR は、少なくとも 1 つのオペランドが true の場合に true を返します。ただし、1 つである必要はありません。両方のオペランドが true の場合、結果は true になります。ただし、排他的 OR は、オペランドの 1 つが true の場合にのみ true を返します。両方のオペランドが true の場合、通常の OR は true (「少なくとも 1 つの true」) を返しますが、XOR は false を返します。これが排他的論理和と呼ばれる理由です。
前述のビット演算子がどのように機能するかを知っていれば、おそらく 277 ^ 432を簡単に計算できるでしょう。しかし、もう一度詳しく見てみましょう :) 100010101
^ 110110000 _______________ 010100101 - ^ の結果
オペレーター それが私たちの結果です。両方の数値で同じビットは 0 を生成します (「1 つだけ」のテストが失敗したことを意味します)。しかし、0-1 または 1-0 のペアを形成していたビットは 1 になりました。結果は、数値 010100101 です。10 進法では、数値 165 に対応します。計算が正しいかどうかを確認してみましょう。
public class Main {
public static void main(String[] args) {
System.out.println(277^432);
}
}
コンソール出力:
165 スーパー! すべては私たちが考えたとおりです:) 次に、ビットシフト演算子について学びましょう。名前自体がそれを物語っています。いくつかの数値を取得し、そのビットを左または右に移動します:) それがどのように見えるかを見てみましょう:
左にシフト
左へのビットのシフトは
<<で示されます 。次に例を示します。
public class Main {
public static void main(String[] args) {
int x = 64;//value
int y = 3;// Shift distance
int z = (x << y);
System.out.println(Integer.toBinaryString(x));
System.out.println(Integer.toBinaryString(z));
}
}
この例では、数値 x = 64 を値と呼びます。シフトするのは値のビットです。
ビットを左にシフトします ( <<演算子の方向からこれを推測できます) 2 進数システムでは、数値 64 = 1000000 になります。数値
y = 3はシフト距離と呼ばれます。
シフト距離は、数値xのビットを右/左に何ビットシフトするかを示します 。この例では、左に 3 ビットシフトします。シフトプロセスをより明確に確認するには、画像を見てください。
この例では、 intを使用します。int はコンピュータのメモリ内で 32 ビットを占有します。元の番号 64 は次のようになります。
そして今、各ビットを文字通り左に 3 桁シフトします。
何が得られたか見てみましょう。ご覧のとおり、すべてのビットがシフトされ、範囲の端からさらに 3 つのゼロが追加されています。3 つシフトしたため、3 つです。10 つシフトした場合は、10 個のゼロが追加されたことになります。したがって、式
x << yは、「数値xのビットをy 桁左にシフトする」ことを意味します。式の結果は 1000000000 という数値になります。これは 10 進法では 512 です。確認しよう:
public class Main {
public static void main(String[] args) {
int x = 64;//value
int y = 3;// Shift distance
int z = (x << y);
System.out.println(z);
}
}
コンソール出力:
512 スポットオン! 理論的には、ビットを無限にシフトできますが、数値が int であるため
、使用できる 2 進数は 32 桁のみです。このうち、7 つはすでに 64 (1000000) によって占有されています。したがって、左に 27 桁シフトすると、唯一の桁がデータ型の範囲を超えて失われます。ゼロだけが残ります。
public class Main {
public static void main(String[] args) {
int x = 64;//value
int y = 26;// Shift distance
int z = (x << y);
System.out.println(z);
}
}
コンソール出力:
0 予想通り、ビットは利用可能な 32 ビットを超えて消えました。最終的には 0 だけで構成される 32 ビットの数値になりました。
当然、10進法では0に相当します。左へのシフトを覚えるための簡単なルールは次のとおりです。左へのシフトごとに、数値は 2 倍されます。ビットのピクチャなしで次の式を計算してみましょう 111111111 << 3 数値 111111111 を 2 で乗算する必要があり
ます。結果として、888888888 が得られます。コードを書いて確認してみましょう。
public class Main {
public static void main(String[] args) {
System.out.println(111111111 << 3);
}
}
コンソール出力:
888888888
右にシフト
この操作は
>>で表されます。同じことをしますが、方向が異なります。:) 車輪の再発明はしません。同じ
int 64 で試してみましょう。
public class Main {
public static void main(String[] args) {
int x = 64;//value
int y = 2;// Shift distance
int z = (x >> y);
System.out.println(z);
}
}
右に 2 シフトした結果、数値内の 2 つの極端なゼロが範囲外に移動し、失われます。10000 が得られます。これは、10 進数の 16 に対応します。 コンソール出力:
16 右へのシフトを覚えるための簡単なルールは次のとおりです。右への各シフトは 2 で除算され、余りは破棄されます。たとえば、35
>> 2 は、35 を 2 で 2 回割り、余りを破棄する必要があることを意味します。
35/2 = 17 (余り 1 を破棄) 17/2 = 8 (余り 1 を破棄) 最終的に、35
>> 2 となるはずです。 8 に等しい必要があります。確認してみましょう:
public class Main {
public static void main(String[] args) {
System.out.println(35 >> 2);
}
}
コンソール出力:
8
Java における演算子の優先順位
コードを書いたり読んだりしていると、複数の演算を組み合わせた式を見つけることがよくあります。それらが実行される順序を理解することは非常に重要です (そうしないと、結果に驚くかもしれません) Java には多数の操作があるため、それぞれの操作には特別なテーブル内の場所が割り当てられています。
演算子の優先順位
オペレーター |
優先順位 |
接尾辞 |
expr++ expr-- |
単項 |
++expr --expr +expr ~ ! |
乗法 |
* / % |
添加剤 |
+ - |
シフト |
<< >> >>> |
関連した |
< > <= >=インスタンス |
平等 |
== != |
ビットごとの AND |
& |
ビット単位の排他的論理和 |
^ |
ビットごとの包含的 OR |
| |
論理積 |
&& |
論理和 |
|| |
三項 |
? : |
割り当て |
= += -= *= /= %= &= ^= |= <<= >>= >>>= |
すべての操作は、優先順位を考慮して左から右に実行されます。たとえば、次のように書くと、
int x = 6 - 4/2;
その場合、除算演算 (
4/2 ) が最初に実行されます。2 番目にありますが、優先順位は高くなります。括弧と括弧は最大の優先順位を示します。おそらく学校でのことを覚えているでしょう。たとえば、式に追加すると、
int x = (6 - 4)/2;
この場合、括弧で囲まれているため、減算が最初に実行されます。論理
&&演算子の優先順位はかなり低いため (表を参照)、通常は最後になります。例えば:
boolean x = 6 - 4/2 > 3 && 12*12 <= 119;
この式は次のように実行されます。
boolean x = 6 - 2 > 3 && 12*12 <= 119;
boolean x = 6 - 2 > 3 && 144 <= 119;
boolean x = 4 > 3 && 144 <= 119;
次に、比較演算子が実行されます。
boolean x = true && 144 <= 119;
boolean x = true && false;
そして最後に、AND 演算子 (
&& ) が最後に実行されます。
boolean x = true && false;
boolean x = false;
たとえば、add(
+ ) 演算子は!= (等しくない) 比較演算子よりも優先されます。したがって、式では、
boolean x = 7 != 6+1;
最初に 6+1 演算が実行され、次に 7 != 7 チェック (false と評価される)、そして最後に結果 (false) が変数 x に代入されます (代入は通常、すべての演算子の優先順位が最も低くなります。
参照)テーブル)。ふう!とても大きなレッスンでしたが、やり遂げました!このレッスンまたは前のレッスンの一部が完全には理解できなかったとしても、心配する必要はありません。これらのトピックについては、今後何度か触れていきます。論理演算と数値演算に関する CodeGym のレッスンがいくつかあります。すぐにはこれらに到達することはできませんが、今読んでも害はありません。
GO TO FULL VERSION