Java中的位運算符號解讀(&、|、^、~、<<、>>、>>>)
1. 位運算符號概覽
符號 | 描述 | 運算規(guī)則 |
---|---|---|
& | 與 | 兩個位都為1時,結果才為1 |
| | 或 | 兩個位都為0時,結果才為0 |
^ | 異或 | 兩個位相同為0,不同為1 |
~ | 取反 | 所有位置0變1,1變0 |
<< | 左移 | 各二進位全部左移若干位,高位丟棄,低位補0 |
>> | 帶符號右移 | 各二進位全部右移若干位,低位丟棄,高位補為符號位 |
>>> | 無符號右移 | 各二進位全部右移若干位,低位丟棄,高位補0 |
還有兩個符號,并不是位運算符,但是容易與位運算符混淆,后面將與其相似的位運算符進行一并講解:
符號 | 描述 | 運算規(guī)則 |
---|---|---|
&& | 邏輯與 | 左右表達式均為true時,運算最終結果才為true |
|| | 邏輯非 | 左右表達式只要有一個為true,運算最終結果就為true |
2. 一個工具
下面的函數(shù)可以幫助我們打印Java中int整型的在底層的32位信息,后面可以使用該工具對程序進行調試:
public static void print(int num) { for (int i = 31; i >= 0; i--) { System.out.print((num & (1 << i)) == 0 ? "0" : "1"); } System.out.println(); } // print(1); --> 00000000000000000000000000000001 // print(-1); --> 11111111111111111111111111111111 // print(Integer.MAX_VALUE); --> 01111111111111111111111111111111 // print(Integer.MAX_VALUE); --> 10000000000000000000000000000000
下面開始對每個符號進行介紹。
3. 按位與(&)、邏輯與(&&)
**按位與(&)**的具體運算規(guī)則為:
1 & 1 = 1 1 & 0 = 0 0 & 1 = 0 0 & 0 = 0
// 舉例: print(123); // 00000000000000000000000001111011 print(321); // 00000000000000000000000101000001 print(a & b); // 00000000000000000000000001000001 // 任何數(shù)與0相與都等于0 // 任何數(shù)與自己相與都等于自己
在Java中,(&)不僅可以作為位運算符號,同樣也可以作為邏輯與符號,
要注意:(&&)并不是位運算符號,不可以參與位運算!
**邏輯與(&)、邏輯與(&&)**的具體運算規(guī)則為:
true & true = true true & false = false false & true = false false & false = false true && true = true true && false = false false && true = false false && false = false
兩者的區(qū)別在于:
**邏輯與(&)**在運算時,不論(&)前面的表達式的結果是否為false,(&)后面的表達式都會執(zhí)行運算;
而**邏輯與(&&)**在運算時,如果(&&)前面的表達式的結果為false,則(&&)后面的表達式就不會執(zhí)行運算。
4.按位或(|)、邏輯或(||)
**按位與(&)**的具體運算規(guī)則為:
1 | 1 = 1 1 | 0 = 1 0 | 1 = 1 0 | 0 = 0
// 舉例: print(123); // 00000000000000000000000001111011 print(321); // 00000000000000000000000101000001 print(a | b); // 00000000000000000000000101111011 // 任何數(shù)與0相或都等于自身 // 任何數(shù)與自己相或都等于自己
在Java中,(|)不僅可以作為位運算符號,同樣也可以作為邏輯與符號。
要注意:(||)并不是位運算符號,不可以參與位運算!
**邏輯或(|)、邏輯或(||)**的具體運算規(guī)則為:
true | true = true true | false = true false | true = true false | false = false true || true = true true || false = true false || true = true false || false = false
兩者的區(qū)別在于:
**邏輯或(|)**在運算時,不論(|)前面的表達式的結果是否為true,(|)后面的表達式都會執(zhí)行運算;
而**邏輯或(||)**在運算時,如果(||)前面的表達式的結果為true,則(||)后面的表達式就不會執(zhí)行運算。
5. 異或(^)
**異或(^)**的具體運算規(guī)則為:
1 ^ 1 = 0 1 ^ 0 = 1 0 ^ 1 = 1 0 ^ 0 = 0
// 即相同為0,不同為1
// 舉例: print(123); // 00000000000000000000000001111011 print(321); // 00000000000000000000000101000001 print(a ^ b); // 00000000000000000000000100111010 // 任何數(shù)與0異或都等于自身 // 任何數(shù)與自己異或都為0
6. 取反(~)
**取反(~)**的具體運算規(guī)則為:
~1 = 0 ~0 = 1
// 舉例: print(123); // 00000000000000000000000001111011 print(~a); // 11111111111111111111111110000100 // 符號位也取反
**取反(~)**可以用來求相反數(shù):
// 一個32整數(shù),取反再+1,就是該數(shù)的相反數(shù),效果等同于加負號(-) int a = 123; System.out.println(a); // 123 System.out.println(~a+1); // -123
說明:
由于Java中int類型的整數(shù)范圍為 − 2 31 ∼ 2 31 − 1 -2^{31}\sim2^{31}-1 −231∼231−1,負數(shù)的個數(shù)比正數(shù)多一個,這樣就導致,所有的正數(shù)都有相應的負的相反數(shù),但是并不是所有的負數(shù)都有正的相反數(shù):
a = Integer.MIN_VALUE; System.out.println(a); // -2147483648 print(a); // 10000000000000000000000000000000 System.out.println(~a+1); // -2147483648 print(~a + 1); // 10000000000000000000000000000000 // Java中int整數(shù)最小值的相反數(shù)還是其自身 // 如果一定需要對int整數(shù)最小值求相反數(shù),請將int類型換為long類型
7. 左移(<<)
左移表示的是某數(shù)的各二進位全部左移若干位,高位丟棄,低位補0
// 舉例: print(123); // 00000000000000000000000001111011 print(123 << 1); // 00000000000000000000000011110110 // 整體左移1位,高位丟棄,低位補0
應用:
// 左移1位相當于在原數(shù)的基礎上乘以2 System.out.println(123); // 123 System.out.println(123<<1); // 246 // 左移2位相當于在原數(shù)的基礎上乘以4 System.out.println(2); // 2 System.out.println(2<<2); // 8 // 左移3位、4位...以此類推
8. 帶符號右移(>>)、無符號右移(>>>)
**帶符號右移(>>)**指的是各二進位全部右移若干位,低位丟棄,高位補為符號位
**無符號右移(>>>)**指的是各二進位全部右移若干位,低位丟棄,高位補0
int a = 123; print(a); // 00000000000000000000000001111011 print(a>>2); // 00000000000000000000000000011110 print(a>>>2); // 00000000000000000000000000011110 int b = -123; print(b); // 11111111111111111111111110000101 print(b>>2); // 11111111111111111111111111100001 print(b>>>2); // 00111111111111111111111111100001 // 區(qū)別就在于:一個高位用符號位補,一個高位用0補
Java中沒有(<<<)符號?。?!
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
SpringBoot混合使用StringRedisTemplate和RedisTemplate的坑及解決
這篇文章主要介紹了SpringBoot混合使用StringRedisTemplate和RedisTemplate的坑及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12Spring類型轉換 ConversionSerivce Convertor解析
這篇文章主要介紹了Spring類型轉換 ConversionSerivce Convertor的相關資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-11-11關于springboot的接口返回值統(tǒng)一標準格式
這篇文章主要介紹了關于springboot的接口返回值統(tǒng)一標準格式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-05-05SpringBoot2零基礎到精通之JUnit 5與指標監(jiān)控
SpringBoot是一種整合Spring技術棧的方式(或者說是框架),同時也是簡化Spring的一種快速開發(fā)的腳手架,本篇讓我們一起學習JUnit 5與指標監(jiān)控2022-03-03