JavaRush /Java Blog /Random-JA /Java の論理演算子

Java の論理演算子

Random-JA グループに公開済み
Java の論理演算。 Java のビット演算 - 1

Java の論理演算

論理演算はブール演算子を使用して実行されます。トートロジーで申し訳ありませんが、これがまさに現状です。(プログラミングや数学における) 基本的な論理演算は論理引数 (オペランド) に適用でき、数値の算術演算と同様に、より複雑な式を形成するために使用することもできます。たとえば、次のような式があります。

(a | b) | (c < 100) & !(true) ^ (q == 5)
は 4 つのオペランドを持つ複雑な論理式です: (a | b)、 とаb型変数 ですboolean (c < 100) (true) (q == 5) 。同様に、単純な論理式(a | b)も 2 つのオペランド引数で構成されます。 論理オペランドは、 true または false、 trueまたはfalseと言える式です。Java の用語では、ブール オペランドは型またはブールの式ですboolean。次に例を示します。
  • (2 < 1)— 論理オペランド、その値はfalse
  • true- 値が明らかにtrueである論理オペランド
  • boolean a- Boolean aのような論理オペランドにすることもできます
  • int a = 2-は論理オペランドではなく、単なる型の変数ですint
  • String a = "true"論理オペランドではありません。これは、テキスト値が である文字列です"true"
Java では次の論理演算が使用できます。
  • 論理否定NOT反転とも呼ばれます。!Javaではオペランドの前に「 」記号を付けて表します。1 つのオペランドに適用されます。
  • 論理的な and はAND接続詞でもあります。&適用される 2 つのオペランド間の「 」記号で示されます。
  • 論理または Java では- OR、論理和でもあります。Java では、2 つのオペランド間の記号「|」で示されます。
  • 排他的または、、XOR厳密な論理和。Java では、2 つのオペランド間の記号「^」で示されます。
  • Java では、論理演算子には、条件付きのor||と、条件付きの and -が含まれます&&
注:数理論理学でも同値関係、つまり平等を考慮します。ただし、Java では、等価演算子は==論理演算子とは見なされません。 注意!Java では、論理演算子&、 、|^整数にも適用されます。この場合、それらの動作は少し異なり、ビット単位(またはビット単位) 論理演算子と呼ばれます。それらについては、記事の終わりの方にあります。各 Java 論理演算子を簡単に説明した表を見てみましょう。以下では、それらをさらに詳しく説明し、コード例を示します。
Java オペレーター 名前 タイプ 簡単な説明
! 論理的な「否定」 単項 !x「×ではない」という意味です。オペランドがfalseの場合はtrueを返します。オペランドがtrueの場合はfalseを返します。 boolean x = true;
それから
// !x == false
& 論理積 ( AND、乗算) バイナリ 両方のオペランドが true の場合はtrue返します。 a = true;
b = false;
それから
a & b == false
| 論理和 ( OR、加算) バイナリ 少なくとも 1 つのオペランドがtrueの場合、 trueを返します。 a = true;
b = false;
それから
a | b == true
^ 排他的論理和 ( XOR) バイナリ オペランドの 1 つだけがtrueの場合、 trueを返します。両方のオペランドがtrueまたはfalseの場合、 falseを返します。基本的に、オペランドが異なる場合はtrueを返します。 a = true;
b = false;
それから
a ^ b == true
&& 条件付き AND (短い論理 AND) バイナリ と同じです&が、 の左側のオペランドが false の場合&、この演算子は2 番目のオペランドをチェックせずにfalseを返します。
|| 条件付き OR (短い論理 OR) バイナリ と同じです|が、左側の演算子がtrueの場合、演算子は2 番目のオペランドをチェックせずにtrueを返します。

JavaRushコースの論理演算

論理演算から逃れることはできません。JavaRush コースでは、論理演算は条件およびブール データ型とともに最初のレベルから登場します。プログラマーは、数学的論理の手法の使い方を徐々に学びます。論理的な構成でより自信を持って操作するには、一定の器用さと特定のプロセスの理解が必要です。そのため、これらの操作は、マルチスレッドの探求の最後に、まったく異なるレベルでより詳細にアプローチされます。このとき、ほとんどの学生は、構文や構造に直接気を取られなくなり、タスクの本質を掘り下げようとします。

Java の論理演算。 Java のビット演算 - 2

論理否定演算子 !

この演算子は単項です。つまり、単一のブール式またはオペランドに適用されます。他の否定と同様、理解するのは非常に簡単です。演算子は単に式の意味を反対の意味に変更するだけです。真理値表または否定演算の実行結果:
!a
間違い 真実
真実 間違い
例。論理否定演算
public class Solution {
   public static void main(String[] args) {
       boolean a = true;
       System.out.println(!a); // here our boolean expression reverses its value
       System.out.println(!false); // non-false expression, as you might guess, will be equal to... what?
       System.out.println(!(2 < 5)); // expression (2 < 5) is true, so its negation is false

   }
}
プログラムの出力は次のようになります。

false
true
false

論理 AND - &、および条件付き AND - &&

論理 AND または論理積は 2 つの式に適用され、その結果は両方のオペランドが true の場合にのみtrue になります。つまり、aorオペランドの 1 つがfalsebの場合、 2 番目の演算子の値に関係なく、式はfalseになります。trueが数値 1、false が0 であると考えると、この演算子は通常の乗算​​とまったく同じように機能します。したがって、論理積は「論理積」と呼ばれることがあります。ちなみに、この事実は、演算子の操作をすぐに覚えて、論理演算子または演算子と混同しないようにするのに役立ちます。真理値表、そしてそれはオペレーターの作業の結果でもありますa & b&&|&
ある b a&b
真実 真実 真実
真実 間違い 間違い
間違い 真実 間違い
間違い 間違い 間違い
論理 AND、接続詞でもあります。例:
public class Solution {
   public static void main(String[] args) {
       boolean a = true;
       boolean b = false;
       boolean c = true;
       System.out.println(a & b); // if we multiply true by false, we will definitely get false
       System.out.println(a & c); // true to true will be true
       System.out.println(false & (2 > 5));
 System.out.println((2 < 5) & false);
 // regardless of the truthfulness of the expression in brackets, in which case we have to be content with false
   }
}
プログラムの結果:

false
true
false
false
この演算子は&&「短い AND」と呼ばれることもあります。演算子として論理オペランドを操作する場合も、同じ結果が生成されます&。しかし、彼の仕事自体には違いがあります。したがって、a & b式 () のオペランドがfalseaの場合、オペランドの値をチェックするのは無意味であることにすでに気づいたでしょう。演算の結果は間違いなくfalseになります。したがって、基本的に 2 番目のオペランドの値が必要ない場合は、それを使用することでプログラム内の計算の数を減らすことができます。例のすべての演算子をに置き換えると、結果はまったく同じになりますが、プログラム自体の実行は少し速くなります (ただし、ミリマイクロについて話しているため、これには気づきません...要するに、非常に小さな時間単位)。 b&&&&&

論理 OR は演算子 || であり、条件付き OR も演算子 || です。

Java の OR 演算子は、 という記号で表されます|。論理 OR または論理和は 2 つの式に適用され、両方のオペランドが false の場合に限り、その結果は false になります。ここでは、演算子の場合とある程度同じ状況が観察されます&が、まったく逆です。つまり、少なくとも 1 つのオペランドがtrueの場合、 2 番目の演算子の値に関係なく、式はtruea | bであることが保証されます。論理乗算のように動作する場合、 trueが 1、falseが 0 であると想像すると、OR は論理加算になります。論理加算は通常の加算とは動作が異なることに注意してください。この場合の 1 + 1 は 2 ではなく 1 に等しいです (この系には 2 という数字は存在しません)。論理和は 0 と 1 の最大値として理解される場合があります。この場合、少なくとも 1 つのオペランドが 1 ( true ) に等しい場合、正確にtrueが得られます。OR 真理値表。演算子の結果とも呼ばれます。 &|
ある b | b
真実 真実 真実
真実 間違い 真実
間違い 真実 真実
間違い 間違い 間違い
論理和 (論理和とも呼ばれます) の例:
public class Solution {
   public static void main(String[] args) {
       boolean a = true;
       boolean b = false;
       boolean c = true;
       System.out.println(!a | b); // Compose the use of two logical operators: a == true, so !a, as we already know, is false.
       System.out.println(a | c);
       System.out.println((2 < 5) | false); // expression (2 < 5) is true, which means that for any second operand we get a true result
       System.out.println((2 > 5) | true);

   }
}
結果:

false
true
true
true
||の代わりに 条件付き OR 演算子を使用すると|、まったく同じ結果が得られますが、条件付き AND の場合と同様、&&経済的に動作します。最初のオペランドがtrueに「遭遇」した場合、 の値は2 番目のオペランドはチェックされませんが、結果はすぐにtrueになります。

XOR Java - 排他的論理和 - 演算子 ^

XOR、モジュロ 2 加算、論理 XOR、論理減算、厳密な論理和、ビット単位の補数など、^ブール代数では演算子に多くの名前があります。この演算子を 2 つのオペランドに適用した結果は、オペランドが異なる場合はtrueになり、オペランドが同じ場合はfalseになります。したがって、ゼロ ( false ) と 1 ( true )の減算と比較すると便利です。真理値表XOR。演算子の結果とも呼ばれます^
ブール値 a ブール値 b a^b
真実 真実 間違い
真実 間違い 真実
間違い 真実 真実
間違い 間違い 間違い
例:
public class Solution {
   public static void main(String[] args) {
       boolean a = true;
       boolean b = false;
       boolean c = true;
       System.out.println(!a ^ b); // Compose the use of two logical operators: a == true, so !a, as we already know, is false.
       System.out.println(a ^ c);
       System.out.println((2 < 5) ^ false);
       System.out.println((2 > 5) ^ true);
   }
}
結果:

false
false
true
true

論理演算の優先順位

数学と同様に、プログラミングでも、演算子が同じ式に出現する場合、それらの演算子には特定の実行順序があります。単項演算子は二項演算子よりも優れており、乗算 (論理的であっても) は加算よりも優れています。論理演算子はリスト内で上位にランク付けされており、優先順位も高くなります。
  1. !
  2. &
  3. ^
  4. |
  5. &&
  6. ||
例を見てみましょう。結合と論理和 (&|) には異なる優先順位があります。
public class Solution {
   public static void main(String[] args) {
       boolean a = true, b = true, c = false;
       System.out.println(a | b & c);
}
左から右に進む場合、つまり、最初に演算子を適用して|から - を適用する&と、値falseが得られます。しかし実際には、このプログラムを実行すると、論理 AND 演算子の方が論理 OR 演算子よりも優先されるため、出力は確実にtrueになります。混乱を避けるために、何が乗算のように動作し、何が加算のように動作するかを覚えておく必要があります。優先順位を変更することができます。学校の数学と同じように、括弧を使用するだけです。サンプルコードを少し変更してみましょう。 &|&|
public class Solution {
   public static void main(String[] args) {
       boolean a = true, b = true, c = false;
       System.out.println((a|b)&c);
}
どうしたの?最初に括弧内の論理加算を使用し、次に乗算を使用します。結果はfalseになりますになります。

複雑な論理式

もちろん、ブール式と演算子を組み合わせることができます。記事の冒頭の表現を思い出してみましょう。
(a | b) | (c < 100) & !(true) ^ (q == 5)
今はそれほど怖くはないようです。、 、の値をあらかじめ決めておき、aその値を表示するプログラムを書いてみましょう。複雑なブール式の値を計算する例 bсq
public class Solution {
   public static void main(String[] args) {
       boolean a = true;
       boolean b = false;
       int c = 25;
       int q = 2;
       System.out.println((a|b) | (c < 100) & !(true)^(q == 5));
   }
}
注記:変数qの型は ですintが、q == 5これはブール式であり、上記では数値 2 で初期化しているため、falseqと等しくなります。変数 も同様ですcこの数値は 25 に等しくなりますが、 (c < 100) はtrueに等しいブール式です。このプログラムの結果:

true
複雑なブール式は、非常に複雑で分岐のある条件をテストするために使用できますが、過度に使用すべきではありません。コードが読みにくくなります。

ビット単位 (ビット単位) 演算子

この記事の冒頭で、演算子 と を Java 整数型に関連して使用できることを説明し &まし|^。この場合、それらはビット単位の演算子です。1 桁が 1 ビットであり、これらの演算は特にビットを扱うため、ビット単位とも呼ばれます。もちろん、論理演算子とは動作が多少異なり、その仕組みを正確に理解するには、2 進数体系とは何かを知る必要があります。それについて何も知らない場合、または完全に忘れてしまった場合は、まず「Java: ビットとバイト」の記事を読んで、2 進数体系には 0 と 1 の 2 つの数字しかなく、すべてのデータが存在することを他の人に思い出してもらうことをお勧めします。コンピュータでは、条件付きの 0 と 1 を使用して正確に表現されます。私たちが慣れ親しんでいる数字 (10 進数、0 から 9 までの 10 個の異なる数字があり、任意の数字を書きます) はすべて 2 進数体系で表すことができます。数値体系の基数 (2) を使用して列に順次除算することにより、10 進数を 2 進数に変換できます。各ステップの割り算の余りを逆の順序で書くと、目的の 2 進数が得られます。たとえば、ここでは 10 進数 103 を 2 進数表現に変換します。 Java の論理演算。 Java のビット演算 - 3

JavaRush コースの 2 進数システム

JavaRush コースでは、マルチスレッド クエスト (レベル 10、講義 1) を学習しながら 2 進数システムについて話します。講義の後には、統合するためのいくつかのタスクがあります。ただし、このトピックはまったく難しいものではありません。コースをまだそこまで学習していなくても、おそらく理解できるでしょう。

および に加えて、&Javaではビット単位の演算子も使用されます。 |^
  • ~ ビットごとの否定演算子
  • >>ビット単位で右シフト
  • >>>符号なしビット単位右シフト
  • <<ビット単位で左シフト
初心者にとって、ビット単位の演算子は非常にわかりにくく、不自然に見えます。彼らは、教育上の問題を解決すること以外に、自分たちが何に必要とされているかを理解していないことがほとんどです。実際、それらは効率的な除算と乗算を組織するために最小限で使用でき、専門家はそれらをエンコード/デコード、暗号化、および乱数の生成に使用します。

ビット演算子 &、| そして^

これらの演算子がどのように機能するかの例を見てみましょう。2 つの整数があるとします。
int a = 25;
int b = 112; 
&これらに 3 つの操作を適用し、結果を画面に表示する|必要 があります。^プログラムコードは次のとおりです。
public class Solution {
   public static void main(String[] args) {

       int a = 25;
       int b = 112;

       int res1 = a & b;
       int res2 = a | b;
       int res3 = a ^ b;

       System.out.println("a & b = " + res1);
       System.out.println("a | b = " + res2);
       System.out.println("a ^ b = " + res3);

   }
}
プログラムの結果は次のようになります。

a & b = 16
a | b = 121
a ^ b = 105
何が起こっているのか理解していないと、結果は非常に神秘的に見えます。実際、すべては思っているよりも単純です。ビット演算子は、バイナリ形式のオペランド番号を「参照」します。次に、両方の数値の対応する桁 (ビット) に論理演算子&または|を適用します^。したがって、&数値 25 のバイナリ表現の最後のビットは、数値 112 のバイナリ表現の最後のビット、最後から 2 番目のビットと最後から 2 番目の 1 と論理的に加算されます。同じロジックは Java の論理演算。 Java のビット演算 - 4、の場合|^Java の論理演算。 Java のビット演算 - 5

左または右にビットシフト

Java にはビット シフト演算子がいくつかあります。最も一般的に使用される演算子<<は と です>>。これらは、数値の 2 進表現をそれぞれ左または右にシフトし、右にシフトする場合は、符号を保持したままにします (符号の保持が何を意味するかについては、以下で説明します)。もう 1 つの右シフト演算子があります>>>。同じことを行いますが、>>署名は保存されません。それでは、例を使って彼らの仕事を見てみましょう。 int a = 13 a << 1数値 a のバイナリ表現のすべてのビットを 1 ビット左にシフトします。単純化するために、2 進数の 13 が 0000 1101 であると想像してみましょう。実際、Java はint数値に 4 バイトまたは 32 ビットを割り当てるため、この数値は次のようになります: 00000000 00000000 00000000 00001101。ただし、これはこの例では重要ではないため、この例では数値を 1 バイトであるとみなします。 Java の論理演算。 Java のビット演算 - 6右側の空いたビットはゼロで埋められます。この演算の結果、数値 26 が得られます。 a << 2数値の 2 進表現のすべてのビットがa2 ビット左にシフトされ、右側の空いた 2 ビットはゼロで埋められます。その結果、数値は 52 になります。 a << 3結果は 104 になります... パターンに気づきましたか? an 位置のビット単位の左シフトは、数値aに 2 の n 乗を乗算するのと同じように機能します。負の数にも同じことが当てはまります。これにより、-13 << 3結果は -104 になります。 a >> n数値のバイナリ表現を n 位置右にシフトします。たとえば、13 >> 1 数値 1101 を数値 0110、つまり 6 に変換します。13 >> 2結果は 3 になります。つまり、ここでは数値を 2 の n 乗で割ります。ここで、n はシフト数です。ただし、1 つ注意点があります。数値が奇数の場合、この操作中に数値の最後のビットがリセットされるようです。しかし、マイナスの場合は状況が多少異なります。たとえば、プログラムに操作の実行を要求した場合に、プログラムが何を生成するかを確認してみましょう-13 >> 1。ご想像のとおり、-6 ではなく -7 という数字が表示されます。これは、Java やその他のプログラミング言語での負の数値の格納方法が原因で発生します。これらは、いわゆる相補コードに格納されます。この場合、最上位桁 (左側の桁) が符号の下に表示されます。負の数の場合、最上位桁は 1 です。

追加コード

という数字を考えてみましょうint a = 13。プログラム内でコマンドを使用してそのバイナリ表現をコンソールに出力するとSystem.out.println(Integer.toBinaryString(a));、1101 が得られます。実際、これは省略表記です。型番号はintメモリ内で 4 バイトを占めるため、コンピュータはそれをより「認識」します。このような:

00000000 00000000 00000000 00001101
最上位桁はゼロです。これは正の数であることを意味します。追加のコードに変換するには:
  1. いわゆる「直接コード」に数字 -13 を書きます。これを行うには、数値の最上位桁を 1 に変更します
    。アクションの結果:

    
    10000000 0000000 0000000 00001101
  2. 次に、符号ビットを除くすべてのビットを反転します (0 を 1 に、1 を 0 に変更します)。実際、すでに変更してあります。
    アクションの結果:

    
    11111111 11111111 11111111 11110010

    (はい、ステップ 1 と 2 を組み合わせることができますが、そのように考えたほうがよいでしょう)

  3. 結果の数値に 1 を加算します。
    アクションの結果:

    
    11111111 11111111 11111111 11110011
結果の 2 進数は -13 で、2 の補数コードで書かれており、ビット シフト (およびその他の演算) がこれに特別に適用されます。ただ、すべての操作において、操作ロジックの違いは顕著ではありません。同じ左へのシフトの場合、違いは目立ちません。正の数と同じように負の数を扱うことができます。では、右にシフトしてみましょう-13 >> 1。演算子は>>符号を保持するため、この演算では、左側で解放されたすべてのビットが 0 ではなく 1 で埋められます。したがって、数字をずらすと、

11111111 11111111 11111111 11110011
1 ビット右に移動すると、次のようなビットのシーケンスになります。

11111111 11111111 11111111 11111001
この数値を直接コードに変換すると (つまり、最初に 1 を減算し、最初のビットを除くすべてのビットを反転すると)、次の数値が得られます。

10000000 00000000 00000000 00000111
または -7。符号を保持する右シフト演算子を理解したので、それが演算子とどのように異なるかが明らかになるでしょう>>>a >>> n— この演算は符号なしシフトです。つまり、数値のバイナリ表現をa右に n ビットシフトしますが、左側に空いた n ビットは、演算子のように 1 ではなく>>、ゼロで埋められます。操作をしてみましょう-13 >>> 1-13すでに2 の補数の 数値が得られています。

11111111 11111111 11111111 11110011
1 ビット右にシフトし、空きビットを 0 で埋めると、次の数値が得られます。

01111111 11111111 11111111 11111001
10進数表記の数字とは何ですか?2147483641

ビットごとの否定演算子 ~

この単項演算子は非常に簡単に機能します。整数の 2 進表現の各ビットを反転します。数字を見てみましょう-13:

11111111 11111111 11111111 11110011
ビット単位の否定演算は、~13各ビットの値を単純に反転します。結果として、次のことが得られます。

00000000 00000000 00000000 00001100
または1210 進数形式で。

簡単な結論

  • すべての論理演算子は、ブール式、つまりtrueまたはfalseと言える式に適用されます。
  • 演算子&|または が^数値に適用される場合、私たちは論理演算について話しているのではなく、ビット単位の演算について話していることになります。つまり、両方の数値が 2 進数に変換され、論理的な加算、乗算、または減算の演算がビットごとにこれらの数値に適用されます。
  • 数学的論理では、演算子&と は|論理積と論理和に対応します。
  • 論理 AND は、1 ( true ) と 0 ( false ) の乗算に似ています。
  • 論理 OR は、1 ( true ) と 0 ( false )の最大値を見つけることに似ています。
  • 整数 a のビット単位の否定には、 演算子 が使用されます~a
  • ブール式 a を論理的に否定するには、演算子 を使用します!a
  • 負の数は 2 の補数コードで保存および処理されます。
  • 右へのビット単位のシフトでは、>>符号 ( >>>) が保持される場合と保持されない場合があります。
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION