【C++ 筆記】運算子(下) - part 5
===
目錄(Table of Contents):
[TOC]
---
很感謝你點進來這篇文章。
你好,我並不是什麼 C++、程式語言的專家,所以本文若有些錯誤麻煩請各位鞭大力一點,我極需各位的指正及指導!!本系列文章的性質主要以詼諧的口吻,一派輕鬆的態度自學程式語言,如果你喜歡,麻煩留言說聲文章讚讚吧!
運算子(Operator)
---
讓我們回顧 part 3 內容,
C++ 有支援以下運算子:
* 算術運算子 - part 3 已學過
* 關係運算子 - part 3 已學過
* 邏輯運算子
* 位元運算子
* 指定運算子
* 運算元(Operand):在運算式中,運算元是資料的值。在例子「1 + 1」當中,兩個「1」都是運算元,運算元是被操作、運算的物件。
* 運算子(Operator):運算子是一個進行操作的符號。在例子「1 + 1」當中,「+」就是一個運算子,表示加法操作、運算。
* 運算式(Expression):運算式是由運算元和運算子組成的結構,用於進行計算並回傳結果。在例子中,「1 + 1」就是一個運算式,進行加法運算並回傳結果為「2」。
算術運算子:就是數學運算子,+、-、*、/、%、++、-- 等運算子。
關係運算子(比較運算子):
| 運算子 | 描述 |
| -------- | -------- |
| == | 比較兩個運算元是否相等。是則回傳 true,不是則回傳 false。 |
| != | 比較兩個運算元是否「***不***」相等。是則回傳 true,不是則回傳 false。 |
| > | 比較左運算元是否大於右運算元。是則回傳 true,不是則回傳 false。 |
| < | 比較左運算元是否小於右運算元。是則回傳 true,不是則回傳 false。 |
| >= | 比較左運算元是否「***大於或等於***」右運算元。是則回傳 true,不是則回傳 false。 |
| <= | 比較左運算元是否「***小於或等於***」右運算元。是則回傳 true,不是則回傳 false。 |
### 邏輯運算子(Logical Operator)
---
| 運算子 | 描述 |
| -------- | -------- |
| && | 邏輯 AND 運算子,如果兩個運算元都是 true,則條件為 true。 |
| || | 邏輯 OR 運算子,如果兩個運算元中其中一個是 true,則條件為 true。 |
| ! | 邏輯 NOT 運算子,主要用來反轉邏輯狀態的運算子,像是 (A&&B) 若為 true,則 !(A&&B) 為 false。 |

Image Source:[Advanced Search Techni... | Klingemann Library LibGuides](https://libguides.berlin-international.de/books/how-to-search/page/advanced-search-techniques)
以上是 AND、OR、NOT 運算子它們的文氏圖,總之文氏圖的意義在程式語言的 &&、||、! 運算是一樣的。
邏輯運算子主要應用在 if、else if 等等的條件語句當中,具體來說是如何應用呢?
仍然老話一句,繼續練習吧!
```cpp=
#include<iostream>
using namespace std;
int main(){
int a = 10, b = 20;
if (a == 10 && b == 20){
cout << "True" << endl;
}
else{
cout << "False" << endl;
}
a = 5;
if (a == 10 && b == 20){
cout << "True" << endl;
}
else{
cout << "False" << endl;
}
}
```
輸出結果:
```
True
False
```
接下來是 || 邏輯 OR 運算子的範例:
```cpp=
#include<iostream>
using namespace std;
int main(){
int a = 10, b = 20;
if (a == 10 || b == 20){
cout << "True" << endl;
}
else{
cout << "False" << endl;
}
a = 5;
if (a == 10 || b == 20){
cout << "True" << endl;
}
else{
cout << "False" << endl;
}
}
```
輸出結果:
```
True
True
```
接下來是 ! 邏輯 NOT 運算子的範例:
```cpp=
#include<iostream>
using namespace std;
int main(){
int a = 10, b = 20;
if (!(a == 10 && b == 20)){
cout << "True" << endl;
}
else{
cout << "False" << endl;
}
a = 5;
if (!(a == 10 || b == 20)){
cout << "True" << endl;
}
else{
cout << "False" << endl;
}
}
```
輸出結果:
```
False
False
```
結合 &&、|| 運算子,能夠新增更多的條件,避免產生 if 巢狀判斷的情況,比如說以上面範例的 && 運算子舉例,如下程式碼:
```cpp=
#include<iostream>
using namespace std;
int main(){
int a = 10, b = 20;
if (a == 10){
if (b == 20){
cout << "True" << endl;
}
}
else{
cout << "False" << endl;
}
a = 5;
if (a == 10){
if (b == 20){
cout << "True" << endl;
}
}
else{
cout << "False" << endl;
}
}
```
輸出結果:
```
True
False
```
以上程式碼適用於 && 運算子的巢狀判斷寫法,至於 || 運算子的寫法,我想各位讀者可以自己玩看看。
### 位元運算子(Bitwise Operator)
---
C++ 當中,提供了 AND(&)、OR(|)、NOT(!)、XOR(^)、補數(~)complement 等位元運算子。
* AND 表示兩真值成立才得以成立,也就是運算元都必須是 1。
* OR 表示兩真值其中之一個成立就可以成立,也就是所有運算元當中其中一個是 1 即可成立。
* NOT 表示反轉邏輯,如 AND 運算過後的結果是 1,則使用 ! NOT 運算子會讓它變成 0。
* XOR 表示兩真值其中之一個成立就可以成立,***且必須沒有交集***,交集意思就是 1、1,0、0,兩個運算元是有相同的值。
二進位轉換器:[即時十進位轉二進位轉換器 - Yeecord 小工具](https://tools.yeecord.com/zh-tw/base-converter/dec/bin)
二進位轉十進位徒手算法:
假設 1100100,從最右邊的 0 開始,為 0*2的0次方,左邊下一個也是 0,為 0*2的1次方,以此類推,之後將這些值全部相加,得總和就能算出十進位的數字。
假設 A = 100、B = 87。
則 A、B 二進位分別為:
A = 1100100
B = 1010111
A & B = 1000100 = 十進位的 68
A | B = 1110111 = 十進位的 119
A ^ B = 0110011 = 十進位的 51
~A = 0011011 = 十進位的 27
註:補數(~)complement 將二進位的 0 轉換成 1,1 轉換成 0,就這樣,就是整個把它顛倒過來。

***以上是 A & B 文氏圖,作者繪製。***

***以上是 A OR B 文氏圖,作者繪製。***

***以上是 A XOR B 文氏圖,作者繪製。***
接下來讓我們針對以上的運算子來進行練習~~(範例取自:[邏輯運算、位元運算](https://openhome.cc/Gossip/CppGossip/LogicalBitwise.html))
```cpp=
#include <iostream>
using namespace std;
int main() {
cout << "AND 運算:" << endl;
cout << "0 AND 0\t\t" << (0 & 0) << endl;
cout << "0 AND 1\t\t" << (0 & 1) << endl;
cout << "1 AND 0\t\t" << (1 & 0) << endl;
cout << "1 AND 1\t\t" << (1 & 1) << endl;
cout << "OR 運算:" << endl;
cout << "0 OR 0\t\t" << (0 | 0) << endl;
cout << "0 OR 1\t\t" << (0 | 1) << endl;
cout << "1 OR 0\t\t" << (1 | 0) << endl;
cout << "1 OR 1\t\t" << (1 | 1) << endl;
cout << "XOR 運算:" << endl;
cout << "0 XOR 0\t\t" << (0 ^ 0) << endl;
cout << "0 XOR 1\t\t" << (0 ^ 1) << endl;
cout << "1 XOR 0\t\t" << (1 ^ 0) << endl;
cout << "1 XOR 1\t\t" << (1 ^ 1) << endl;
cout << "NOT 運算:" << endl;
cout << "NOT 0\t\t" << (!0) << endl;
cout << "NOT 1\t\t" << (!1) << endl;
return 0;
}
```
輸出結果:
```
AND 運算:
0 AND 0 0
0 AND 1 0
1 AND 0 0
1 AND 1 1
OR 運算:
0 OR 0 0
0 OR 1 1
1 OR 0 1
1 OR 1 1
XOR 運算:
0 XOR 0 0
0 XOR 1 1
1 XOR 0 1
1 XOR 1 0
NOT 運算:
NOT 0 1
NOT 1 0
```
以下是利用位元運算判斷偶、奇數的程式碼(範例取自:[邏輯運算、位元運算](https://openhome.cc/Gossip/CppGossip/LogicalBitwise.html)):
```cpp=
#include <iostream>
using namespace std;
int main() {
int input = 0;
cout << "輸入正整數:";
cin >> input;
cout << "輸入為奇數?"
<< (input & 1 ? 'Y' : 'N')
<< endl;
return 0;
}
```
輸出結果:
```
輸入正整數:5
輸入為奇數?Y
```
> 這個程式的原理是,奇數的數值若以二進位來表示,其最右邊的位元必為 1,而偶數最右邊的位元必為 0,所以使用 1 來與輸入的值作 AND 運算,由於 1 除了最右邊的位元為 1 之外,其它位元都會是 0,與輸入數值 AND 運算的結果,只會留下最右邊位元為 0 或為的結果,其它部份都被 0 AND 運算遮掉了。
總之,讓輸入的數字跟二進位 " 1 ",注意喔,只有 1 而已,所以它只會跟最二進位的最右邊位元進行運算。
而最右邊的位元我們剛剛說過,轉換成十進位會變成 1 * 2 的 0 次方,也就是會變成 1,而如果位元是 0 的話就是 0 * 2 的 0 次方,變成 0。
1 是奇數,0 是偶數。
然後讓我們介紹一下左移、右移運算子(<<、>>)。
「<<」:左移運算子,將一個運算物件的各二進位位元全部左移某位元(左邊的位元放棄,右邊補 0)。
「>>」:右移運算子,將一個運算物件的各二進位位元全部右移某位元(右邊的位元放棄,正數左邊補 0、負數左邊補 1)。
舉例:a = 60,二進位為 0011 1100。
則 a << 2 表示全部往左移兩位:1111 0000。
則 a >> 2 表示全部往右移兩位:0000 1111。
練習一下:
```cpp=
#include <iostream>
using namespace std;
int main()
{
int a = 60, c = 0;
c = a << 2; // 240 = 1111 0000
cout << "a 進行左移後 c is : " << c << endl ;
c = a >> 2; // 15 = 0000 1111
cout << "a 進行右移後 c is : " << c << endl ;
return 0;
}
```
輸出結果:
```
a 進行左移後 c is : 240
a 進行右移後 c is : 15
```
別睡著了!
哈囉,你還醒著嗎?
看起來還醒著,讓我們繼續吧!
### 指定運算子(Assignment Operator)
---
指定運算子就是用於簡化變數指定流程的一種運算子,以下是個表格:
| 運算子 | 描述 | 實例 |
| -------- | -------- | -------- |
| = | 指定運算子。 | c = a + b,將 a + b 運算過後指定給 C。 |
| += | 加和指定運算子。 | c += a 等於 c = c + a。 |
| -= | 減和指定運算子。 | c -= a 等於 c = c - a。 |
| *= | 乘和指定運算子。 | c *= a 等於 c = c * a。 |
| /= | 除和指定運算子 | c /= a 等於 c = c / a。 |
| %= | 取模和指定運算子。 | c %= a 等於 c = c % a。 |
| <<= | 左移和指定運算子。 | c <<= a 等於 c = c << a。 |
| >>= | 右移和指定運算子。 | c >>= a 等於 c = c >> a。 |
| &= | AND位元運算子和指定運算子。 | c &= a 等於 c = c & a。 |
| ^= | XOR位元運算子和指定運算子。 | c ^= a 等於 c = c ^ a。 |
| |= | OR位元運算子和指定運算子。 | c |= a 等於 c = c | a。 |
練習一下:
```cpp=
#include <iostream>
using namespace std;
int main()
{
int a = 21;
int c ;
cout << "初始值 a = " << a << endl;
c = a;
cout << "c = a -> " << c << endl;
c += a;
cout << "c += a -> " << c << endl;
c -= a;
cout << "c -= a -> " << c << endl;
c *= a;
cout << "c *= a -> " << c << endl;
c /= a;
cout << "c /= a -> " << c << endl;
c = 200;
c %= a;
cout << "c %= a -> " << c << endl;
c <<= 2;
cout << "c <<= 2 -> " << c << endl;
c >>= 2;
cout << "c >>= 2 -> " << c << endl;
c &= 2;
cout << "c &= 2 -> " << c << endl;
c ^= 2;
cout << "c ^= 2 -> " << c << endl;
c |= 2;
cout << "c |= 2 -> " << c << endl;
return 0;
}
```
輸出結果:
```
初始值 a = 21
c = a -> 21
c += a -> 42
c -= a -> 21
c *= a -> 441
c /= a -> 21
c %= a -> 11
c <<= 2 -> 44
c >>= 2 -> 11
c &= 2 -> 2
c ^= 2 -> 0
c |= 2 -> 2
```
總結
---
有關於其他運算子的相關名詞解釋可看這篇(作者推薦):[運算子的優先權 - HackMD](https://hackmd.io/@ndhu-programming-2021/HJAkAf8AF#%E5%89%8D%E8%A8%80)
***邏輯運算子(Logical Operator):***
| 運算子 | 描述 |
| -------- | -------- |
| && | 邏輯 AND 運算子,如果兩個運算元都是 true,則條件為 true。 |
| || | 邏輯 OR 運算子,如果兩個運算元中其中一個是 true,則條件為 true。 |
| ! | 邏輯 NOT 運算子,主要用來反轉邏輯狀態的運算子,像是 (A&&B) 若為 true,則 !(A&&B) 為 false。 |

Image Source:[Advanced Search Techni... | Klingemann Library LibGuides](https://libguides.berlin-international.de/books/how-to-search/page/advanced-search-techniques)
邏輯運算子主要應用條件判斷上面,邏輯運算子通常用於布林運算式當中,如:true && false。
***位元運算子(Bitwise Operator):***
C++ 當中,提供了 AND(&)、OR(|)、NOT(!)、XOR(^)、補數(~)complement 等位元運算子。
* AND 表示兩真值成立才得以成立,也就是運算元都必須是 1。
* OR 表示兩真值其中之一個成立就可以成立,也就是所有運算元當中其中一個是 1 即可成立。
* NOT 表示反轉邏輯,如 AND 運算過後的結果是 1,則使用 ! NOT 運算子會讓它變成 0。
* XOR 表示兩真值其中之一個成立就可以成立,***且必須沒有交集***,交集意思就是 1、1,0、0,兩個運算元是有相同的值。
補數(~)complement 將二進位的 0 轉換成 1,1 轉換成 0。
***指定運算子(Assignment Operator):***
指定運算子就是用於簡化變數指定流程的一種運算子。
| 運算子 | 描述 | 實例 |
| -------- | -------- | -------- |
| = | 指定運算子。 | c = a + b,將 a + b 運算過後指定給 C。 |
| += | 加和指定運算子。 | c += a 等於 c = c + a。 |
| -= | 減和指定運算子。 | c -= a 等於 c = c - a。 |
| *= | 乘和指定運算子。 | c *= a 等於 c = c * a。 |
| /= | 除和指定運算子 | c /= a 等於 c = c / a。 |
| %= | 取模和指定運算子。 | c %= a 等於 c = c % a。 |
| <<= | 左移和指定運算子。 | c <<= a 等於 c = c << a。 |
| >>= | 右移和指定運算子。 | c >>= a 等於 c = c >> a。 |
| &= | AND位元運算子和指定運算子。 | c &= a 等於 c = c & a。 |
| ^= | XOR位元運算子和指定運算子。 | c ^= a 等於 c = c ^ a。 |
| |= | OR位元運算子和指定運算子。 | c |= a 等於 c = c | a。 |
今日已學 C++ 運算子當中的:
* 邏輯運算子
* 位元運算子
* 指定運算子
參考資料
---
[快速搞懂位元運算子的 AND. 位元運算子是用於處理二進位數字的運算符號。這些運算符號通常用於程式語言中,並對二… | by Roan | Medium](https://medium.com/@roan6903/%E5%BF%AB%E9%80%9F%E6%90%9E%E6%87%82-javascript-%E4%BD%8D%E5%85%83%E9%81%8B%E7%AE%97%E5%AD%90%E7%9A%84-and-fdf60531473f)
[邏輯運算、位元運算](https://openhome.cc/Gossip/CppGossip/LogicalBitwise.html)
[C++ 运算符 | 菜鸟教程](https://www.runoob.com/cplusplus/cpp-operators.html)