Java 移位、邏輯運算符詳解(~史上最全|吹牛逼)

目錄

一、<< :左移運算符

二、>> :右移運算符

三、>>> :無符號右移

四、& :與運算

五、| :或運算

六、~ :非運算 

七、^ :異或運算

拓展問題:

一:從計算速度上講,移位運算要比算術運算快?

二:二進制的起源

日常發車:


參考文章:
https://blog.csdn.net/is_zhoufeng/article/details/8112199

一、<< :左移運算符

說明:將運算符左邊的對象向左移動運算符右邊指定的位數(在低位補0)
通俗含義:num << 1,相當於num乘以2,依次數字遞增,乘以2的平方(不嚴謹)

例如:

2 << 1 //4 移了一位2*2

2 << 2 //8 移了兩位 2*2*2

2 << 3 //16 移了三位 2*2*2*2

 

二、>> :右移運算符


說明:如果值爲正,則在高位補0,如果值爲負,則在高位補1.
通俗含義:num >> 1,相當於num除以2,依次數字遞增,除以2的平方(不嚴謹)

例如:

16 >> 1 //8 移了一位 16/2

16 >> 2 //4 移了兩位 16/2/2

16 >> 3 //2 移了三位 16/2/2/2


三、>>> :無符號右移


說明:忽略符號位,高位都以0補齊
含義:無符號右移運算符>>>  結果總是正數或者0 

爲什麼只對正數有意義,對負數沒有什麼算術意義,只有邏輯意義:
因爲如果一個數位負數,按照現實中數學常識,除以或乘一個負數都是負數,但在程序中都是正數顯示

爲什麼只是對32位和64位的值有意義 ?
例如:

System.out.println(-1024 >> 4); //-64

System.out.println(-1024 >>> 4); //268435392

System.out.println(1024 >>> 24); //0


引申:
與(&)、非(~)、或(|)、 從電路的角度理解 

“門”是這樣的一種電路:它規定各個輸入信號之間滿足某種邏輯關係時,纔有信號輸出。
從邏輯關係看,門電路的輸入端或輸出端只有兩種狀態,無信號以“0”表示,有信號以“1”表示。

產生:通常有下列三種門電路:與門、或門、非門(反相器)

0爲假,1爲真     =====》
true ——> 1
false ——> 0

四、& :與運算

說明;符號兩邊都爲true,結果纔是true,否則爲false;對於數字,可將數字轉換爲2進制形式去理解,採用同位 與 操作即可得出結果。
聯想:在與運算中兩個開關是串聯的,如果我們要開燈,需要兩個開關都打開燈纔會打開。

例如:

true&true=true

true&false=false

false&false=false

2&3=2 即:0010&0011=0010 (從高位到低位,依次做與操作)

五、| :或運算

說明:符號兩邊只有有一個爲true,則結果爲true,否則爲false;對於數字,可將數字轉換爲2進制形式去理解,採用同位 或 操作即可得出結果。
聯想:在或運算中兩個開關是並聯的,即一個開關開,則燈開。

例如:

true|true=true

true|false=true

false|true=true

false|false=false

2|3=3 即:0010|0011=0011 (從高位到低位,依次做或操作)


六、~ :非運算 


聯想:非門輸出與輸入相反,即取反運算

例如:


!true=false

!false=true

System.out.println(~2);//-3

System.out.println(~-2);//1

七、^ :異或運算

說明:相同爲0,不同爲1;對於數字,可將數字轉換爲2進制形式去理解,採用同位 異或 操作即可得出結果。
含義:異或是一種基於二進制的位運算,用符號XOR或者 ^ 表示,其運算法則是對運算符兩側數的每一個二進制位,同值取0,異值取1。

重要性質:
自反性:A XOR B XOR B = A xor  0 = A
即對給定的數A,用同樣的運算因子(B)作兩次異或運算後仍得到A本身

不進位加法:如1+1=0,,0+0=0,1+0=1。

實際應用:
利用自反性,可以獲得許多有趣的應用。 例如,所有的程序教科書都會向初學者指出,要交換兩個變量的值,必須要引入一箇中間變量。但如果使用異或,就可以節約一個變量的存儲空間: 設有A,B兩個變量,存儲的值分別爲a,b,則以下三行表達式將互換他們的值 表達式 (值) :

 A=A XOR B (a XOR b)

 B=B XOR A (b XOR a XOR b = a) 

 A=A XOR B (a XOR b XOR a = b)

 類似地,該運算還可以應用在加密,數據傳輸,校驗等等許多領域。

常規測試:

2^3=1,即0010^0011=0001

true^true=false

false^false=false

true^false=true

5^2=7 即:0101^0010=0111 (從高位到低位,依次做異或操作)

 

拓展問題:

 

一:從計算速度上講,移位運算要比算術運算快?


參考:https://blog.csdn.net/fyilun/article/details/45168253

CPU角度:
因爲移位指令佔2個機器週期,而乘除法指令佔4個機器週期。

 

因爲移位指令不需要涉及到邏輯運算.

常規一條指令被拆分的步驟
IF    ID    EX    MEM     WB UP
取指、譯碼、執行、訪存、寫回、更新

移位指令:取指 、寫回(寫)
乘除法指令:取指、譯碼、執行、寫回(一次邏輯運算和一次寫)

從硬件上看,移位對硬件更容易實現,所以會用移位,移一位就乘2,這種乘法當然考慮移位了。

實際應用角度,JVM的自主優化:
對於乘法和以及%運算,JVM一定會優化,這些是不需要程序員去考慮的,直接去用*/%即可。
對於除法,因爲上述問題,確實是位移更快些。不過通常還是考慮使用位運算:
例如JVM源碼:

java.util.Arrays.binarySearch:

int low = fromIndex;
int high = toIndex - 1;

while (low <= high) {
    int mid = (low + high) >>> 1;
    int midVal = a[mid];

    if (midVal < key)
        low = mid + 1;
    else if (midVal > key)
        high = mid - 1;
    else
        return mid; // key found
}
return -(low + 1);  // key not found.

解析:(low + high) >>> 1代替(low + high) /2是非常正確的,首先是因爲數組下標肯定不會是負數,另一方面如果low + high大於int最大值(溢出變爲負數了)時,只有>>>1能保證結果正確。

 

二:二進制的起源

中國的《易經》以爻、卦來表示天地和萬物,其中爻是最基本的元素,爻分陰爻(用“--”表示)和陽爻(用“—”表示)兩種,陰爻和陽爻的不同排列就是卦象,一個卦象稱爲一卦,一卦由六爻組成一卦就是一個整體。

世界萬物中最基本的要素有8種,分別是天、地、雷、風、水、火、山和澤,他們分別用八卦表示,即乾、坤、震、坎、離、艮、兌,八卦互相搭配又得六十四卦,用來表示各種自然現象和人事現象。

我們對比二進制的組成:二進制的位用0,1表示,3位二進制可組合成8種狀態,即可表示爲0,1,...,7這8個數,而2個3位二進制組合,即變爲6位二進制數,即:2=64,即64種狀態。


萊布尼茲是第一個認識到二進制記數法重要性的人,並系統地提出了二進制數的運算法則。二進制對200多年後計算機的發展產生了深遠的影響。他於1716年發表了《論中國的哲學》一文,
還設計了一臺可以完成數碼計算的機器。並進行了二進制的推廣。

參考:
https://zhidao.baidu.com/question/1177745006240062179.html


聯想到
我們爲什麼使用二進制去作爲基本元素?

核心:兩個狀態的系統容易實現 、運算法則簡單、可進行邏輯運算。

運算規則簡單:節省設備。人們知道,具有兩種穩定狀態的元件(如晶體管的導通和截止,繼電器的接通和斷開,電脈衝電平的高低等)容易找到,而要找到具有10種穩定狀態的元件來對應十進制的10個數就困難了

適合邏輯運算:邏輯代數是邏輯運算的理論依據,二進制只有兩個數碼,正好與邏輯代數中的“真”和“假”相吻合

容易實現:二進制在物理上最易實現存儲,通過磁極的取向、表面的凹凸、光照的有無等來記錄。

日常發車:


程序員的工作是相對孤獨的,如何平衡呢?看下圖:

圖片等

發佈了240 篇原創文章 · 獲贊 91 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章