JavaRush /Java Blog /Random-TW /Java 中的邏輯運算符

Java 中的邏輯運算符

在 Random-TW 群組發布
Java 中的邏輯運算。 Java 中的位元運算 - 1

Java中的邏輯運算

邏輯運算是使用布林運算子執行的。請原諒我的同義反复,但事情確實就是這樣。基本邏輯運算(在程式設計和數學中)可以應用於邏輯參數(操作數),也可以用來形成更複雜的表達式,類似於數字的算術運算。例如表達式:

(a | b) | (c < 100) & !(true) ^ (q == 5)
是一個具有四個運算元的複雜邏輯運算式: (a | b),其中аb是類型變數boolean (c < 100) (true) (q == 5) 。反過來,簡單邏輯運算式(a | b)也由兩個運算元參數組成。 邏輯運算元是一個可以說是 true 或 false、truefalse的表達式。在 Java 術語中,布林操作數是類型或布林值的表達式boolean,例如:
  • (2 < 1)— 邏輯運算元,其值為false
  • true- 其值顯然為true 的邏輯運算元
  • boolean a- 也可以是邏輯運算元,如布林值 a
  • int a = 2-不是邏輯運算元,它只是類型變量int
  • String a = "true"也不是邏輯運算元。這是一個文字值為 的字串"true"
Java 中有以下邏輯運算:
  • 邏輯否定,也稱為NOT反轉。在Java中,是用!操作數前的「 」符號來表示的。適用於一個操作數。
  • 邏輯 and,它也是AND一個連接詞。&由應用它的兩個操作數之間的“ ”符號指示。
  • 邏輯或在Java中,它也是- OR,它也是析取。在Java中,用兩個操作數之間的符號「|」來表示。
  • 異或, XOR, 嚴格析取。在Java中,用兩個操作數之間的符號「^」來表示。
  • 在 Java 中,邏輯運算子包括條件 or,表示為||,以及條件 and - &&
注意:在數理邏輯中,他們也考慮等價關係,換句話說,相等。但是,在 Java 中,等號運算子==不被視為邏輯運算子。 注意力!在 Java 中,邏輯運算子&,|^也適用於整數。在這種情況下,它們的工作方式略有不同,稱為位元邏輯運算子。關於他們 - 在文章的最後。讓我們看一下表格,其中簡要描述了每個 Java 邏輯運算符,下面我們將更詳細地描述它們並提供程式碼範例。
Java運算符 姓名 類型 簡短的介紹 例子
! 邏輯“非”(否定) 一元 !x意思是「不是x」。如果操作數為false,則傳回true。如果操作數為true則回傳false boolean x = true;
然後
// !x == false
& 邏輯與(AND,乘法) 二進位 如果兩個操作數都為true則傳回true a = true;
b = false;
然後
a & b == false
| 邏輯或(OR,加法) 二進位 如果至少有一個操作數為true ,則傳回true a = true;
b = false;
然後
a | b == true
^ 邏輯異或 ( XOR) 二進位 如果一個且只有一個操作數為true ,則傳回true。如果兩個操作數均為truefalse則傳回false。本質上,如果操作數不同,則傳回true 。 a = true;
b = false;
然後
a ^ b == true
&& 條件 AND(短邏輯 AND) 二進位 與 相同,&但如果 左側的操作數&false,則該運算子傳回false而不檢查第二個操作數。
|| 條件 OR(短邏輯 OR) 二進位 與 相同,|但如果左側的運算子為true,則該運算子傳回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 或合取應用於兩個表達式,只有當兩個運算式都為 true 時,其結果才會為 true。也就是說,如果aor運算元之一bfalse ,則無論第二個運算子的值為何,表達式都會a & bfalse 。如果您想像true是數字 1,false是 0,那麼該運算子的工作&方式與常規乘法完全相同。因此,邏輯與通常被稱為“邏輯乘法”。順便說一句,這個事實有助於快速記住運算符的操作&,而不是將其與邏輯或運算符混淆|。真值表AND,也是運算子工作的結果&
A 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表達式 () 中的操作數afalse,則檢查操作數的值就沒有意義b:運算結果肯定為false。因此,如果我們根本不需要第二個運算元的值,那麼使用它&&可以減少程式中的計算次數。如果我們將範例中的所有運算子替換&&&,結果將完全相同,但程式本身會運行得更快一些(儘管我們不會注意到這一點,因為我們正在談論 mili-micro...簡而言之,非常小的時間單位)。

邏輯或是運算子|,條件或是運算子||

Java 中的 OR 運算子以符號 表示|。邏輯或或析取應用於兩個表達式,且僅當兩個操作數都為假時,其結果將為假。在這裡,我們在某種程度上觀察到與運算符 的情況相同的情況&,但恰恰相反。也就是說,如果至少一個運算元為true ,則無論第二個運算子的值為何,表達式a | b都保證為true 。如果&它的行為類似於邏輯乘法,那麼 OR 就是邏輯加法,如果您想像true為 1,false為 0。請記住,邏輯加法的工作方式與普通加法不同。在這種情況下,1 + 1 不等於 2,而是等於 1(數字 2 在這個系統中根本不存在)。有時析取被理解為 0 和 1 中的最大值,在這種情況下,如果至少一個操作數等於 1 ( true ),我們就得到完全true。OR 真值表,也稱為運算子的結果|
A 一個 | 乙
真的 真的 真的
真的 錯誤的 真的
錯誤的 真的 真的
錯誤的 錯誤的 錯誤的
邏輯或,也稱為析取,例如:
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,則不檢查第二個操作數,但結果立即為true

XOR Java - 邏輯異或 - 運算子 ^

XOR、模2加法、邏輯異或、邏輯減法、嚴格析取、按位補…運算子^在布林代數中有很多名字。如果運算元不同,則將此運算子套用至兩個運算元,結果將為true ;如果運算元相同,則結果為false 。因此,用減去零( false)和減去一(true )來比較它是很方便的。真值表XOR,又稱運算符的結果^
布林值 布林值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);
       System.out.println((2 > 5) ^ true);
   }
}
結果:

false
false
true
true

邏輯運算的優先權

就像在數學中一樣,在程式設計中,當運算子出現在同一表達式中時,它們具有特定的執行順序。一元運算子比二元運算子有優勢,乘法(甚至邏輯)比加法有優勢。我們將邏輯運算子排列在清單中越高,它們的優先順序就越高:
  1. !
  2. &
  3. ^
  4. |
  5. &&
  6. ||
讓我們看一下例子。連接詞和析取 ( &and |) 有不同的優先權:
public class Solution {
   public static void main(String[] args) {
       boolean a = true, b = true, c = false;
       System.out.println(a | b & c);
}
如果我們從左到右進行操作,即先應用運算符|,然後應用 - &,我們將得到值false。但事實上,如果您執行該程序,您將確定輸出將為true,因為邏輯 AND 運算子&將比邏輯 OR 運算子具有更高的優先權|。為了避免混淆,您需要記住什麼&行為類似於乘法,|什麼行為類似於加法。您可以更改優先順序。只需使用括號,就像學校數學一樣。讓我們稍微改變一下範例程式碼:
public class Solution {
   public static void main(String[] args) {
       boolean a = true, b = true, c = false;
       System.out.println((a|b)&c);
}
這是怎麼回事?首先我們在括號中使用邏輯加法,然後使用乘法。結果將是錯誤的

複雜的邏輯表達式

當然,我們可以將布林表達式和運算子結合起來。讓我們記住文章開頭的那句話:
(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是一個布林表達式,而且它等於false,因為上面我們用q數字 2 進行了初始化。變數 也是如此c。這個數字等於 25,但 (c < 100) 是一個等於true的布林表達式。該程式的結果:

true
複雜的布林表達式可用於測試非常複雜和分支條件,但不應過度使用它們:它們會使程式碼難以閱讀。

位元(bitwise)運算符

在文章開頭,我們提到運算子 &,|^可以與 Java 整數型別相關。在這種情況下,它們是位元運算子。它們也稱為按位,因為一位數就是一位,而這些運算是專門針對位進行。當然,它們的工作方式與邏輯運算符有些不同,要準確理解它們的工作方式,您需要知道什麼是二進制數字系統。如果你對此一無所知或完全忘記了,我們建議你先閱讀《Java:位元和位元組》一文,並提醒大家,在二進制數係統中只有兩位數-0和1,所有資料在計算機中使用條件零和一來精確表示。我們習慣的任何數字(十進制;對於它們來說,有從 0 到 9 的 10 個不同的數字,我們可以用它們來書寫任何數字)可以用二進制數字系統來表示。您可以使用數字系統基數 (2) 依序除法將十進位數轉換為二進位數。每一步除法的餘數以相反的順序寫出,將為我們提供所需的二進制數。例如,這裡是將十進制數 103 轉換為二進位表示法: Java 中的邏輯運算。 Java 中的位元運算 - 3

JavaRush 課程中的二進位數位系統

在 JavaRush 課程中,他們在學習多執行緒任務(第 10 級,​​講座 1)時談論二進制數字系統;講座結束後有幾個需要鞏固的任務。然而,這個主題一點也不困難,即使您在課程中還沒有學到那麼深,您也可能會弄清楚。

除了,之外&,Java 還使用位元運算子: |^
  • ~ 按位求反運算符
  • >>位元右移
  • >>>無符號位元右移
  • <<位元左移
對於初學者來說,位元運算子似乎非常令人困惑且不自然。除了解決教育問題之外,他們通常不明白自己需要做什麼。事實上,它們至少可以用來組織有效的除法和乘法,專業人士使用它們進行編碼/解碼、加密和產生隨機數。

位元運算子 &, | 和^

讓我們來看看這些運算符如何運作的範例。假設我們有兩個整數:
int a = 25;
int b = 112; 
我們需要對它們進行三個操作&|並將^結果顯示在螢幕上。這是程式碼:
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 的二進位表示形式的最後一位相加,即倒數第二位與倒數第二位,依此類推: 相同的邏輯可以在和的情況。 |^&Java 中的邏輯運算。 Java 中的位元運算 - 4|^Java 中的邏輯運算。 Java 中的位元運算 - 5

向左或向右位移位

Java 中有多種移位運算子。最常用的運算子<<是 和>>。它們分別將數字的二進位表示向左或向右移動,在向右移動的情況下,同時保留符號(我們將在下面解釋保留符號的含義)。還有另一個右移運算子>>>。它做同樣的事情,但>>不保存標誌。那麼,讓我們用一個例子來看看他們的工作。 int a = 13 a << 1將數字 a 的二進位表示形式的所有位元向左移動 1 位元。為了簡單起見,我們將數字 13 想像成二進位的 0000 1101。事實上,這個數字看起來像這樣:00000000 00000000 00000000 00001101,因為 Java為數字分配了int4 個位元組或 32 位元。然而,這在範例中不起作用,因此在本範例中我們將認為我們的數字是一位元組。 Java 中的邏輯運算。 Java 中的位元運算 - 6右側空出的位元用零填滿。此操作的結果是,我們得到數字 26。 a << 2它將數字的二進位表示形式的所有位元a向左移動 2 位,右側空出的兩位數以零填充。結果,我們將得到數字 52。 a << 3結果將是 104...注意到這個模式了嗎?位元a左移 n 個位置就像是將數字a乘以 2 的 n 次方。這同樣適用於負數。這-13 << 3將給出結果-104。 a >> n將數字的二進位表示向右移動 n 位。例如,13 >> 1 將數字 1101 轉換為數字 0110,即 6。13 >> 2結果將是 3。也就是說,本質上,這裡我們將數字除以 2 的 n 次方,其中 n 是移位次數向右,但有一個警告:如果數字是奇數,在此操作期間我們似乎重置了數字的最後一位。但對於消極的情況則有所不同。比方說,如果您要求程式執行一項操作,請嘗試檢查程式將產生什麼結果-13 >> 1。您將看到數字 -7,而不是您想像的 -6。發生這種情況是由於 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
產生的二進制數是 -13,以二進制補碼形式寫入,位移位(和其他操作)將專門應用於它。只是並不是所有操作中操作邏輯上的差異都是明顯的。假設,對於同樣的左移,差異是不明顯的;我們可以像處理正數一樣處理負數。現在讓我們向右移動-13 >> 1。由於我們的運算子>>保留了符號,因此在此操作中,左側釋放的所有位元都不是用零填充,而是用 1 填充。因此,移動數字

11111111 11111111 11111111 11110011
向右移動一位,產生下列位元序列:

11111111 11111111 11111111 11111001
如果我們將這個數字轉換為直接代碼(即先減 1,然後反轉除第一個之外的所有位元),我們會得到這個數字:

10000000 00000000 00000000 00000111
或-7。現在我們已經了解了符號保留右移運算符,它與運算符 的差異就會變得清楚>>>a >>> n— 此操作是無符號移位,也就是說,它將數字的二進位表示形式a向右移動 n 位,但不會像運算子 那樣用 1 填充左側空出的 n 位>>,而是用 0 填充。我們來做手術吧-13 >>> 1-13我們已經有了二進制補碼的 數字:

11111111 11111111 11111111 11110011
透過右移 1 位並用零填充空閒位,我們得到以下數字:

01111111 11111111 11111111 11111001
什麼給了十進制數2147483641

按位求反運算符 ~

這個一元運算子的工作原理非常簡單:它反轉整數的二進位表示的每一位。讓我們看一下數字-13

11111111 11111111 11111111 11110011
按位求反運算~13將簡單地反轉每個位元的值。結果我們得到:

00000000 00000000 00000000 00001100
12十進制形式。

簡要結論

  • 所有邏輯運算子都適用於布林運算式,也就是那些可以說是truefalse 的表達式。
  • Если операторы &, | or ^ применяются к числам, речь идёт уже не о логических операциях, а о побитовых. То есть оба числа переводятся в двоичную систему и к этим числам побитово применяют операции логического сложения, умножения or вычитания.
  • В математической логике операторам & и | соответствуют конъюнкция и дизъюнкция.
  • Логическое И похоже на умножения 1 (true) и 0 (false).
  • Логическое ИЛИ напоминает поиск максимума среди 1 (true) и 0 (false).
  • Для побитового отрицания целого числа a используется операция ~a.
  • Для логического отрицания булевского выражения a используется операция !a.
  • Отрицательные числа хранятся и обрабатываются в дополнительном codeе.
  • Поразрядный сдвиг вправо может сохранять знак (>>), а может — не сохранять (>>>).
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION