我們必須要了解的Java位運算(不僅限於Java)

陳咬金發表於2022-04-26

本文原創地址為 https://www.cnblogs.com/zh94/p/16195373.html

原創宣告:作者:陳咬金、 部落格地址:https://www.cnblogs.com/zh94/

基本概念

1、當前常見的CPU位數是32位和64位,所謂32位處理器就是一次只能處理32位,也就是4個位元組的資料,而64位處理器一次則能處理64位,即8個位元組的資料。關於64位處理器32和64位含義32和64位區別

2、一位元組(1Byte)等於8位(8bit),位是計算機儲存資料的最小單位,也就是計算儲存的資料是一系列二進位制位資訊。每個位用0或1表示。(大B和小b的區別需注意哦)

3、為什麼一個位元組是8位?
現在通用的說法是8位可以涵蓋所有的字元編碼,即ASCII編碼。但歷史上也存在過4位或者7位為1Byte的場景,只是在後續的字符集標準統一中逐漸被8bit所替代。除了歷史原因之外,還有資料儲存的需要(必須要能在一個位元組內表示超過100種狀態,包括常用數字,大小寫字母等),再加上早期計算機儲存價格昂貴,所以8bit也是在當時符合二進位制特性的必然結果。1Byte為何是8bit1Byte為何是8bit二進位制世界祕密

4、二進位制加減運算,加法:0+0=0,0+1=1,1+0=1,1+1=10 ,逢2進1。二進位制加法二進位制減法

5、二進位制轉十進位制及十進位制轉二進位制。2、10進位制互相轉換

上述列出了一些基本概念和對應的可參考連結,建議先優先了解一下。尤其是二進位制和十進位制的互相轉換以及二進位制的加減法規則,在後面都會具體涉及到。

機器數、真值

人類用十進位制完全是因為我們有10個手指頭。如果有一天你看到一個外星人,它只有4個手指頭,那麼他使用的一定是四進位制,如圖所示:

如果能看明白上圖,說明你已經明白了進位制和手指頭的關係了。現代的計算機內部使用閘電路,它們只能表示0或者1兩個狀態。如果計算機是一個人,那麼他只有兩個手指頭,所以它使用二進位制。
是的,就是這樣,所謂的進位制,實際上並不是什麼神祕的東西,只是關於數的一種表示方式而已了。閘電路概念

機器數

機器數分為:無符號數和有符號數兩種。

一個數在計算機中的二進位制表示形式,  叫做這個數的機器數。機器數是帶符號的,在計算機用一個數的最高位存放符號, 正數為0,負數為1。

比如,十進位制中的數 +3 ,計算機字長為8位,轉換成二進位制就是00000011。

如果是 -3 ,就是 10000011 。那麼,這裡的 00000011 和 10000011 就是機器數。

真值

因為第一位是符號位,所以機器數的形式值就不等於真正的數值。

例如上面的有符號數 10000011,其最高位1代表負,其真正數值是 -3 而不是形式值131(10000011轉換成十進位制等於131)。

所以,為區別起見,將帶符號位的機器數對應的真正數值稱為機器數的真值。

例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1

原碼、反碼、補碼

為了妥善的處理資料運算過程中符號位的問題,於是就產生了把符號位和數值位一起編碼起來表示相應的數的各種表示方法。例如我們熟悉的原碼、反碼、補碼、移碼等。通常將未經編碼的數稱為真值,編碼後的數稱為機器數或者機器碼。

計算機當前所使用的機器數是採用的補碼的方式。在探求為何機器要使用補碼之前, 讓我們先了解原碼, 反碼和補碼的概念。對於一個數, 計算機要使用一定的編碼方式進行儲存, 原碼, 反碼, 補碼是機器儲存一個具體數字的編碼方式。

原碼

原碼就是符號位加上真值的絕對值, 即用第一位表示符號, 其餘位表示值. 比如如果是8位二進位制:

[+1]原 = 0000 0001
[-1]原 = 1000 0001

第一位是符號位. 因為第一位是符號位, 所以8位二進位制數的取值範圍就是:

[01111111,11111111]

轉換為真值後即:

[127,-127 ]

原碼是人腦最容易理解和計算的表示方式。原碼也可以理解為最原始的機器碼。

反碼

反碼的表示方法是:
正數的反碼是其本身,
負數的反碼是在其原碼的基礎上, 符號位不變,其餘各個位取反。

[+1] = [00000001]原 = [00000001]反

[-1] = [10000001]原 = [11111110]反

可見如果一個反碼錶示的是負數, 人腦無法直觀的看出來它的數值. 通常要將其轉換成原碼再計算。

補碼

補碼的表示方法是:
正數的補碼就是其本身,
負數的補碼是在其原碼的基礎上, 符號位不變, 其餘各位取反, 最後+1. (即在反碼的基礎上+1)。

[+1] = [00000001]原 = [00000001]反 = [00000001]補
[-1] = [10000001]原 = [11111110]反 = [11111111]補

對於負數, 補碼錶示方式也是人腦無法直觀看出其數值的. 通常也需要轉換成原碼在計算其數值。

互相轉換、注意事項

注意:我們在最初的基本概念中提到了二進位制和十進位制的轉換方式。但是需要知道的是,一個數在計算機中的二進位制表示方式叫做機器數。

而機器數是有符號的,我們將對應的最高位存放符號,0位正數,1位負數。所以機器數並不等於二進位制。

由此我們才引出了真值的概念,例如:符號數 10000011,在十進位制中對應的值為131,但是在機器數中,由於1表示負數,所以其真正數值是-3,而並不是131。

符號數:10000011,我們需要先消除其符號位的影響,將其調整為正數:00000011,此時將正數轉換為10進製為3,然後再加上最初的符號位表示負數,所以為-3。

需知道的是,二進位制僅是以2為基數的計數方式而已,在二進位制中是無法區分正數和負數的。而如果想區分正數和負數那麼必須在二進位制的最高一位中用0和1來表示符號以此來表示正負。那麼此時最高位的0和1已經不是二進位制的一種計數方式了,而只是一種符號的標識,該符號的標識則是萬萬不可以直接參與二進位制的計算的。

當我們用最高位中的0和1來表示正負時,此時該二進位制的數已經不再是符合二進位制規則的數了,而是機器數。

二進位制僅僅是以2為基數的計算方式,此時最高位的值已經不再是通過2位基數的計算方式而計算出來的,而只是一個表示正負的標識了,所以此時該數值則已經不再是符合二進位制規則的數了,而是機器數。

所以,也只有機器數才可以表示正負。而機器數所對應得到的結果則是真數,而並不是10進位制數。

如果此時丟擲來一個問題:10000011 轉換為對應的10進位制,那麼對應的結果則是131,但如果是轉換為真數,則是-3。同樣的,如果是將00000011 轉換為對應的10進位制,則是3,而如果轉換為真數,則也是3。

所以當我們看到一個以8位數所表示的二進位制數時,則一定要確認該二進位制數是表示機器數,還是二進位制數?是轉換為10進位制數,還是真數。其中最大的區別則是,最高的符號位到底是參與二進位制的運算,還是僅僅表示符號位。

機器數轉真數:
10000011 >消除最高位1的影響先轉為正數>00000011>再將該正數以二進位制的方式轉為十進位制為> 3 >此時再將最初的符號新增回來>3調整為-3。

二進位制數轉10進位制數:
10000011 >無需消除最高位1的影響直接轉為正數>10000011>再將該正數以二進位制的方式轉為十進位制為 > 131>無需新增符號位>131仍然為131。

所以可知,真數和10進位制數最大的區別則是是否忽略最高位,在確認完是否忽略最高位,得到最初的正數後,該正數的計算方式,則和二進位制轉十進位制的方式完全相同。其實就是二進位制轉十進位制。哈哈。


那麼在注意了二進位制數和機器數以及十進位制數和真數的區別之後。我們則需要注意的另外一個問題則是:

機器數是包含原碼、反碼、補碼。其中三者之間是可以互相轉換的。原碼轉反碼轉補碼,這塊上面已經說明過了,而補碼則也可以通過想反的方式重新轉換為原碼。

而此處需要知曉的則是,反碼和補碼當然是不可以直接轉為真數的,而必須要通過原碼才可以進行轉換。

這個其實也沒什麼問題,畢竟原碼經過層層轉換後得到補碼,而補碼又可以直接轉換為真數,當然不可能了。

接下來則是,為什麼原碼需要轉換為補碼,為什麼原碼不是計算機的計算方式,而是補碼?

本文原創地址為 https://www.cnblogs.com/zh94/p/16195373.html

原創宣告:作者:陳咬金、 部落格地址:https://www.cnblogs.com/zh94/

為什麼補碼才是計算機的真正計算方式

現在我們知道了計算機可以有三種編碼方式表示一個數. 對於正數因為三種編碼方式的結果都相同:

[+1] = [00000001]原 = [00000001]反 = [00000001]補

所以不需要過多解釋. 但是對於負數:

[-1] = [10000001]原 = [11111110]反 = [11111111]補

可見原碼, 反碼和補碼是完全不同的. 既然原碼才是被人腦直接識別並用於計算表示方式, 為何還會有反碼和補碼呢?

首先, 因為人腦可以知道第一位是符號位, 在計算的時候我們會根據符號位, 選擇對真值區域的加減。
但是對於計算機, 加減乘數已經是最基礎的運算, 要設計的儘量簡單. 計算機辨別"符號位"顯然會讓計算機的基礎電路設計變得十分複雜! 於是人們想出了將符號位也參與運算的方法. 我們知道, 根據運演算法則減去一個正數等於加上一個負數, 即: 1-1 = 1 + (-1) = 0 , 所以機器可以只有加法而沒有減法, 這樣計算機運算的設計就更簡單了。

於是人們開始探索 將符號位參與運算, 並且只保留加法的方法. 首先來看原碼:
計算十進位制的表示式: 1-1=0

1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2

如果用原碼錶示, 讓符號位也參與計算, 顯然對於減法來說, 結果是不正確的.這也就是為何計算機內部不使用原碼錶示一個數。
為了解決原碼做減法的問題, 出現了反碼:
計算十進位制的表示式: 1-1=0

1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0

發現用反碼計算減法, 結果的真值部分是正確的. 而唯一的問題其實就出現在"0"這個特殊的數值上. 雖然人們理解上+0和-0是一樣的, 但是0帶符號是沒有任何意義的. 而且會有[0000 0000]原和[1000 0000]原兩個編碼表示0。

於是補碼的出現, 解決了0的符號以及兩個編碼的問題:

1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]補 + [1111 1111]補 = [0000 0000]補=[0000 0000]原

這裡說明一下,二進位制想加:0000 0001+1111 1111 = 1 0000 0000,但由於是8位數,所以最終的值為 0000 0000。

這樣0用[0000 0000]表示, 而以前出現問題的-0則不存在了.而且可以用[1000 0000]表示-128:

(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]補 + [1000 0001]補 = [1000 0000]補

由於我們使用原碼來表示正時,最大值為:01111111,最小值為:11111111,所以直接轉換為對應的10進位制後的結果為,127,-127。
而此處使用補碼後,由於補碼的規則是,首位不變,其它反轉,並+1。所以(-1)+(-127) 剛好為-128。

使用補碼, 不僅僅修復了0的符號以及存在兩個編碼的問題, 而且還能夠多表示一個最低數. 這就是為什麼8位二進位制, 使用原碼或反碼錶示的範圍為[-127, +127], 而使用補碼錶示的範圍為[-128, 127]。

因為機器使用補碼, 所以對於程式設計中常用到的32位int型別, 可以表示範圍是: [-2的31次方, 2的31次方 - 1] 因為第一位表示的是符號位.而使用補碼錶示時又可以多儲存一個最小值。

Amazing,我們在上面最初使用原碼進行加法運算時,由於我們人腦還需要先判斷一下最高位的符號後,才能進行二進位制運算,然後再新增上對應的符號位。而採用補碼後,直接將對應的符號位也參與運算,將補碼的數值直接相加,得到的竟然剛好也就是二進位制轉換後的結果。這樣一來,計算機的基礎電路設計就可以更加簡單,而無需關注符號位的問題,僅需要按照二進位制的加法法則執行即可。簡直完美。所以這也是補碼作為計算機的真正計算方式的原因之一!

但,補碼後所得到的值想加剛好就是直接二進位制的值相加後的結果,真的是就剛好這麼巧嗎?其實不然,背後還蘊含這很有意思的數學原理,詳情可參考:
深入理解原碼、補碼 & 數的機器碼錶示 & 機器碼原理 & 原碼、補碼原理

位運算

文章最頂部基本概念處列到了“10進位制2進位制互轉”,以及“2進位制加減法”對應的相關連結。
此處再推薦幾個線上計算的網址,便於將自己的計算結果進行二次驗證:
線上原碼、補碼、10進位制互轉 & 線上進位制轉換 & 線上二進位制加減法

接下來則開始涉及到位運算了。

概念

什麼是位運算?我們先來看下百度百科的概念:

程式中的所有數在計算機記憶體中都是以二進位制的形式儲存的。位運算就是直接對整數在記憶體中的二進位制位進行操作。

百度百科中所給的解釋是具備歧義性的,按照百度百科的解釋,直接對整數在記憶體中的二進位制位進行操作就是位運算的話,那麼使用二進位制數進行算術運演算法(+,-,*,/ )豈不是也屬於位運算?

我們再來看下維基百科所給的概念解釋:

位操作是程式設計中對位模式或二進位制數的一元和二元操作。在許多古老的微處理器上,位運算比加減運算略快,通常位運算比乘除法運算要快很多。在現代架構中,情況並非如此:位運算的運算速度通常與加法運算相同(仍然快於乘法運算)。

維基百科中針對位運算的概念相對合理,通過維基百科中的概念我們可以很明顯的區分到,位運算是和加減乘除這些算數運算子是不同的。不同的CPU針對位運算的操作是較快於(乘/除)法運算的。

所以這也才是我們需要了解位運算的真正原因,那就是CPU處理器針對位運算子的計算是快於算術運算子的!在特定的編碼場景下使用位運算的執行速率則是遠遠大於算術運算的!

網路上針對位運算較多的內容解釋是:位運算是直接對整數在記憶體中的二進位制位進行操作,所以位運算更加節省記憶體、提高運算效率等等的。其實這是很不嚴謹的說法,很容易誤導大家對位運算的理解,因為所有的整數最終在計算機中都是二進位制數,那麼所有對整數的運算豈不是都是位運算?當然不是啦。且,位運算真正快的原因也並不是因為節省記憶體,而主要是因為CPU對位運算的支援!和記憶體並沒有較大關聯。

為何位運算CPU執行速率更快

程式中的基本運算包含:

  • 算術運算:加、減、乘、除、取餘
  • 按位運算:按位或“|”、按位與“&”、按位取反“~”、按位異或“^”
  • 移位運算:左移x<<k;右移x>>k

其中按位運算和移位運算均屬於位運算的範疇。

位運算的具體執行邏輯,我們下面會詳細說明。這裡先以位運算中的 與 運算子 “&” 來簡單說明下位運算的主要執行邏輯:
& 與運算子的運算規則是:兩個位都為1時,則結果為1。如:3&5 即 0000 0011& 0000 0101 = 0000 0001,因此 3&5 的值得1。

根據與運算子的規則可知,位運算的整體執行邏輯實際是較為簡單的,更多的是進行位數的比較,從而得到一個結果,這種較為簡單的運算邏輯,則對於CPU處理器來說,在電路的設計中則也會更加簡單許多,以下為與運算子所涉及到的CPU電路圖:

而對於一個除法來說呢,在CPU中所對應的電路圖設計則是這樣的:

可以看到,整個CPU電路圖的設計複雜了不止一個層級,所以這也就是為何位運算比我們人常用的算術運算更快的直接原因了。因為對於整個CPU的執行邏輯來說從設計層面就複雜了很多。


當然,提到CPU的電路圖設計,就不得不提到對應的CPU中電晶體的特性了,而電晶體中所涉及到的開關(01)的特性也就構成了邏輯電路,從而構成了與門、或門、非門、異或門等電路特性。
這塊內容,可以參考如下連結:
位運算中隱藏的CPU祕密
程式中的位運算於基本電路關係
程式中位運算於基本電路-知乎
四位計算機的原理及實現
位運算的理解
程式中的取餘是如何實現的
二進位制乘除法的實現

CPU中的電路設計和數學的演算法實現有著很精妙的聯絡,計算機前輩的力量是無窮的。那到了這裡,我們也就知道了程式中基本運算在執行速率上的真正差別實際上是在CPU這一層級的,瞭解了這些之後,我們也就可以接著開始說明位運算子的真正執行邏輯了。
(位運算僅需進行01的比較,和移位等簡單的邏輯操作,基本上和直接執行二進位制的相加規則一樣,在電路設計和邏輯上均更加簡單,而乘除求餘則在電路的設計中較為複雜)

本文原創地址為 https://www.cnblogs.com/zh94/p/16195373.html

原創宣告:作者:陳咬金、 部落格地址:https://www.cnblogs.com/zh94/

位運算子

首先需知道的是,計算機中執行位運算,肯定是採用的補碼的方式進行的位計算哦,所以對於真值為負數的情況下,必須先轉為補碼才能進行計算。

符號 描述 運算規則
& 兩個位都為1時,結果才為1
| 兩個位都為0時,結果才為0
^ 異或 兩個位相同為0,相異為1
~ 取反 0變1,1變0
<< 左移 各二進位全部左移若干位,高位丟棄,低位補0
>> 右移 各二進位全部右移若干位,對無符號數,高位補0。各編譯器處理方法不一樣,有的補符號位(算術右移),有的補0(邏輯右移)

& 與運算子

運算規則:兩位同時為1,結果才為1,否則結果為0。

0&0=0  0&1=0  1&0=0  1&1=1

例如:2 & -2

注意:負數當然是按照補碼的方式來進行位計算哦。

& 與運算子的用途:

根據與運算子的計算特性,我們常用的使用方式有:
1、判斷奇偶數
我們知道,按照二進位制和十進位制(除二取餘)的換算方式,如果是偶數的情況下,換算為二進位制後末位必然是0,如果是奇數則末位為1。比如:2 >10 ,3 > 11,100 >1100100,121 > 1111001。

所以,我們按照與運算子的運算規則,使用 if(a & 1)1表示為奇數,if(a & 1)0,則表示為偶數。
如:
121 & 1 = 1111001 & 0000001 = 0000001
2 & 1 =10 & 01 =00

使用與運算子的方式,則完全可以替代掉:if (a % 2 == 0) 來判斷奇偶數的方式,且位運算子由於CPU的支援,執行效率也更高。

關於二進位制轉十進位制的方式,參考基本概念中URL即可。

2、取一個數的指定位
比如取數 X=1010 1110 高4位,只需要另外找一個數,令 Y的高4位為1,其餘位為0,即Y=1111 0000,然後將X和Y進行與運算,(X & Y = 1010 1110 & 1111 0000 = 1010 0000)即可得到X 的指定高4位。

如果想獲取X的低4位的數,則將Y的低4位為1,其餘位數為0即可,(X & Y=1010 1110 & 0000 1111=0000 1110)便可得到X的指定低4位。

| 或 運算子

運算規則:兩個位都為0時,則結果為0。否則則為1。

0|0=0  0|1=1  1|0=1  1|1=1

例如:2 | -2 =-2

| 或運算子的用途

首先與和或是兩個相反的概念,所以上述所提到的與的用途,在這裡只要略作改造就也適合於或運算子。但是
目的是一樣的,所以對應相同用途的場景,這裡不再贅述。

1、常用來對一個資料的某些位設定為1
比如將數 X=1010 1110 的低4位設定為1,只需要另找一個數Y,令Y的低4位為1,其餘位為0,即Y=0000 1111,然後將X與Y進行按位或運算(X|Y=1010 1111)即可得到。

同樣的,使用 & 運算子,則可以方便的將某些位設定為 0,如上述的X & Y,將X的低4位設定為0,則
X & Y = 1010 1110 & 1111 0000 = 1010 0000。

以上則說明 & 和 | 靈活運用,其實是可以達到相同效果的。但實際使用中則並不然,首先對於上述低4位設定為1的場景,我們只需要找一個Y的數,令Y的低4位為1,其餘位為0,這樣一個數是很好找的,是一個固定的數,比如:15。轉換為二進位制後為1111。

但如果使用 & 運算子來面對這個場景,則需要找一個Y,Y的第四位為0,其餘位置為1,這樣一個數則很難找,並且隨著位數的不同,值也是不斷變換的,比如:1111 0000=240,但如果是12位數,1111 1111 0000=4080。所以如果使用 & 運算子來在該場景下則是沒有 | 運算子更加方便的。

儘管 & 和 | 的規則相反,可靈活變更,但針對特定場景下,還是使用特定的運算子效果更佳O。

^ 異或運算子

運算規則:兩個位相同為0,相異為1。

0^0=0  0^1=1  1^0=1  1^1=0

例如:2 ^ -2

^ 異或運算子用途

1、交換兩個數

a=a^b;      //a=a^b
b=a^b;      //b=(a^b)^b=a^0=a
a=a^b;      //a=(a^b)^(a^b^b)=0^b=0

交換兩個數的原理,即上面註釋所寫內容。

不使用位運算的方式交換兩個數,則需要定義一箇中間變數C,來承接其中的一個數的交換,對於Java來說,定義一個新的Int 變數C,則表示記憶體中需開闢一個4位元組的空間。

所以根據服務特性來選擇合適的方式即可,對記憶體使用率有強要求則使用位運算,沒要求則都可以。

static void swap(int a, int b) {    int c = a;    a = b;    b = c;}

static void swapBit(int a, int b) {    a = a ^ b;    b = a ^ b;    a = a ^ b;}

~ 取反運算子

運算規則:0變1,1變0。

<< 左移運算子

運算規則:將一個運算物件的各二進位制位全部左移若干位(左邊的二進位制位丟棄,右邊補0)。

設 a=15,即二進位制數00001111,左移2位得00111100,即十進位制數60。

左移一位相當於該數乘以2,左移2位相當於該數乘以2^2=4。上面舉的例子15<< 2=60,即乘了4。
(結論:左移n位等於乘以2的n次方)

設 a=-46,補碼後為,1010 1110,a = a<< 2 將a的二進位制位左移2位、右補0,即得a=1011 1000,轉換為真值後為-56。

設 a=110,補碼後為:0110 1110,a = a<<2 將a 的二進位制位左移2位,右補0,即得 a=1011 1000,轉換為真值後為184。

以此可知,左移n位等於乘以2的n次方,該結論僅適用於該數左移時被溢位捨棄的高位中不包含1的情況,如果溢位的高位中包含1,則不符合上述結論。

>> 右移運算子

運算規則:將一個數的各二進位制位全部右移若干位,正數左補0,負數左補1,右邊丟棄。
例如:a=a>>2 將a的二進位制位右移2位,左補0 或者 左補1需要看被移數是正還是負。

設 a=16,補碼後為00010000,a = a<<2 將a的二進位制位右移2位,左邊補0,即得a=00000100,轉換為真值後為4。

設a=-16,補碼後為11110000,a = a<<2 將a的二進位制位右移2位,左邊補1,得到a=11111100,轉換真值後為-4。

結論:右移運算子,運算元每右移一位,相當於該數除以2。

本文原創地址為 https://www.cnblogs.com/zh94/p/16195373.html

原創宣告:作者:陳咬金、 部落格地址:https://www.cnblogs.com/zh94/

Java位運算

位運算本身就是處理器、計算機自身所提供的能力,所以針對位運算的使用,實際上是不限於任何程式語言的,此處之所以以JAVA為例,主要是因為本人常用的開發語言是JAVA,哈哈。

針對JAVA中位運算的使用,實際上在JDK中有這很豐富的案例,比如:

1、JDK中執行緒池ThreadPoolExecutor的實現當中使用Integer型別(4位元組,32位)其中高3位儲存執行緒池狀態,而低29位儲存執行緒池內有效執行緒數量。

2、比如JDK的HashMap中使用位運算的方式將初始化容量的數值,快速的轉換為2的n次冪。以及計算key的hash時,根據該key的hashCode結果,再將該hashCode的高16位和低16位通過位運算的方式進行混合,以此降低hash碰撞的概率等等。

3、比如我們直接開啟常用的Integer類的原始碼,也會發現裡面有大量的位運算的使用。

此處僅是為了通過上述舉例的方式來以此說明位運算在Java生態中的使用程度,實際上是非常豐富的,並且由於位運算獨特的計算特性,在某些相對特殊的程式碼場景下,使用位運算會意想不到的將問題給簡單化。

如果想了解更多在JAVA中的使用場景和案例,建議大家直接翻看各種原始碼即可。

以上是一些舉例,以下再做一些小的補充說明:

在Java當中的位運算,是隻針對Int型別和Long型別有效(java中,一個int的長度始終是32位,也就是4個位元組,它操作的都是該整數的二進位制數,Long則是64位,表示8位元組。),而對於byte,char,short,當為這三個型別時,JVM會先把他們轉換為Int型別後再進行操作。

使用 toBinaryString() 可以將對應的十進位制轉為對應的補碼。

System.out.println(Integer.toBinaryString(10));//1010
System.out.println(Integer.toBinaryString(-10));//11111111111111111111111111111101
System.out.println(Long.toBinaryString(10));//1010
System.out.println(Long.toBinaryString(-10));//1111111111111111111111111111111111111111111111111111111111110110

如上程式碼可知,Integer和Long轉換為補碼時,Integer為32位,Long是64位。實際上上述的基本型別32位還是64位,均是直接定義在原始碼當中的,感興趣直接看對應的Integer和Long的原始碼即可。

其它參考連結

以下參考連結,僅供參考,部分連結中的內容,可能會具備一些歧義,請讀者自行分辨。

祝福各位讀者所有看到的知識,都可以最終成為自己的知識!撒花!✿✿ヽ(°▽°)ノ✿!

位運算教程
位運算介紹
java位運算
位運算技巧
位運算常用方式

相關文章