JAVA基礎提高之位運算
注:JAVA位運算在閱讀JDK原始碼時候常常會遇到,因此學習位運算相關知識,是非常有必要的,在學習之前,首先需要了解一下二進位制碼相關知識,這裡給大家提供幾篇相關文章:《原始碼,補碼,反碼》
首先,大家都知道,JAVA定義的位運算子可以應用於整數型別(int),長整型(long),短整型(short),字元型(char),和位元組型別(byte)等型別。
Java七種位運算子:
位運算子 | 說明 |
---|---|
>> | 右移運算子,符號左側數值 按位右移 符號右側數值指定的位數,若為正數則高位補0,若為負數則高位補1 |
<< | 左移運算子,符號左側數值 按位左移 符號右側數值指定的位數,並在低位處補0 |
>>> | 無符號右移運算子,符號左側數值 按位右移 符號右側數值指定的位數,無論正負高位補0 |
& | 與(AND)運算子,對兩個整型運算元中對應位執行布林代數,兩個位都為1時輸出1,否則0 |
| | 或(OR)運算子,對兩個整型運算元中對應位執行布林代數,兩個位中只要有一個為1就輸出1,否則為0 |
^ | 異或(XOR)運算子,對兩個整型運算元中對應位執行布林代數,兩個位相等則為0,不相等則為1 |
~ | 非(NOT)運算子,按位取反運算子翻轉運算元的每一位,即0變成1,1變成0 |
七種位運算子使用例項程式碼:
/**
* @Auther: csp1999
* @Date: 2020/10/26/11:33
* @Description: 位運算操作符
*/
public class bit_operators {
@Test
public void test01() {
// int max = Integer.MAX_VALUE;
// int min = Integer.MIN_VALUE;
int num1 = -20;
int num2 = 30;
int bit_operator_1 = num1 << 1;// 正數左移n位擴大2^(n)倍,負數左移n位縮小2^(n)倍
int bit_operator_2 = num1 >> 1;// 正數右移n位縮小2^(n)倍,負數右移n位擴大2^(n)倍
int bit_operator_3 = num1 >>> 1;// 無符號右移 切記要明白計算機儲存二進位制都是以補碼的形式儲存
int bit_operator_4 = num1 & num2;
int bit_operator_5 = num1 | num2;
int bit_operator_6 = num1 ^ num2;
int bit_operator_7 = ~num1;
// System.out.println(max);
// System.out.println(min);
// System.out.println("0"+Integer.toBinaryString(Integer.MAX_VALUE));
// System.out.println(Integer.toBinaryString(20));
System.out.println(bit_operator_1);
System.out.println(bit_operator_2);
System.out.println(bit_operator_3);
System.out.println(bit_operator_4);
System.out.println(bit_operator_5);
System.out.println(bit_operator_6);
System.out.println(bit_operator_7);
}
}
運算結果如下:
-4
-1
2147483647
2
-2
-4
1
原理解析(高位0為手動補齊,方便觀看)
a = 11111111 11111111 11111111 11101100
b = 00000000 00000000 00000000 00011110
------------------------------------------------
a << 1 --> 11111111 11111111 11111111 11011000
a >> 1 --> 11111111 11111111 11111111 11110110
a >>> 1 --> 01111111 11111111 11111111 11110110
a & b = 00000000 00000000 00000000 00001100
a | b = 11111111 11111111 11111111 11111110
a ^ b = 11111111 11111111 11111111 11110010
~a = 00000000 00000000 00000000 00010011
進行位操作時,除long型外,其他型別會自動轉成int型,轉換之後,可接受右運算元長度為32。進行位運算時,總是先將短整型和位元組型值轉換成整型值再進行移位操作的。
資料型別 | 大小 |
---|---|
byte | 8 bit |
short | 16 bit |
char | 16 bit |
int | 32 bit |
long | 64bit |
示例:
byte num1 = -128;
byte num2 = 63;
byte bit_operator_1 = (byte)(a << 1);
byte bit_operator_2 = (byte)(a >> 1);
byte bit_operator_3 = (byte)(a >>> 1);
byte bit_operator_4 = (byte)(a & b);
byte bit_operator_5 = (byte)(a | b);
byte bit_operator_6 = (byte)(a ^ b);
byte bit_operator_7 = (byte)(~ a);
上面的程式碼在位運算後型別自動提升為了int,所以需要使用int型別的變數來接受,但是我們可以在進行位運算後進行強轉,但強轉會直接擷取位元組,從而導致丟失精度,最終得到的結果如下:
0
-64
-64
0
-65
-65
127
對於 int 型別的整數移位 num1 >> num2, 當 b>32 時,系統先用 num2 對 32 求餘(因為 int 是 32 位),得到的結果才是真正移位的位數,例如,num1 >> 33 和 num1 >> 1 的結果相同,而 num1>> 32 = num1;
位運算的使用場景如下:
1.判斷奇偶
@Test
public void test02() {
Integer num = 123;
// 判斷奇偶普通方式一:
if (num % 2 == 0) {
System.out.println("偶數");
} else {
System.out.println("奇數");
}
// 判斷奇偶位運算方式二:
if ((num & 1) == 0) {
System.out.println("偶數");
} else if ((num & 1) == 1) {
System.out.println("奇數");
}
}
偶數的最低位肯定是0,奇數的最低位肯定是1,而1的最低位是1其他位都為零,當進行與運算時:
- 偶數必然:a&1 == 0
- 奇數必然:a&1 == 1
2. 不使用中間變數交換兩個數
@Test
public void test03() {
int a = 10;
int b = 20;
// 1.依靠中間變數交換2個數值:
int c;
c = a;
a = b;
b = c;
System.out.println("a=" + a + ",b=" + b);
// 2. 位運算不使用中間變數交換2個數:
a = 10;
b = 20;
a = a ^ b;
b = b ^ a;
a = a ^ b;
System.out.println("a=" + a + ",b=" + b);
}
這裡需要知道兩點:
- 任何數和自己進行異或操作結果都為0
- 異或符合交換律,即a ^ b = b ^ a
好的,那麼上面程式碼操作就等於:
a = a ^ b;
b = b ^ a = b ^ (a ^ b) = a;
a = a ^ b = (a ^ b) ^ (b ^ (a ^ b)) = (a ^ b) ^ a = b;
3. 判斷一個正整數是不是2的整數次冪
public boolean power(int num) {
if (num <= 0) {
System.out.println("這裡不計算負數,直接返回false");
return false;
} else {
return (num & (num - 1)) == 0;
}
}
@Test
public void test04() {
int num = 1024;
System.out.println(power(num));
}
任何正整數如果是2的冪數,都形如下:
10
100
1000
10...0
1234
即首位都為1,往後位數都為0,那麼在減去1後又都形如下:
01
011
0111
01...1
1234
所以大於零的2的冪數和自己減一後的數進行與運算結果必然為0
4. 對稱加密
就是使用一次異或加密,使用兩次異或解密:
@Test
public void test5(){
String a = "sadfsdfsdfhfghf123dfgfg";
System.out.println(a);
int key = 324545231;
byte[] bytes = a.getBytes();
for (int i = 0; i < bytes.length-1; i++) {
bytes[i] = (byte)(bytes[i] ^ key);
}
String b = new String(bytes);
System.out.println(b);
for (int i = 0; i < bytes.length-1; i++) {
bytes[i] = (byte)(bytes[i] ^ key);
}
String c = new String(bytes);
System.out.println(c);
}
列印結果:
sadfsdfsdfhfghf123dfgfg
����������������������g
sadfsdfsdfhfghf123dfgfg
以上是JAVA位運算的基本例項和知識點,同樣位運算也廣泛應用於JDK原始碼中,對於初次學習JDK原始碼的小夥伴,位運算基本知識是需要的。最後給大家推薦一個寶藏博主:[棗麵包]
相關文章
- Java 基礎 之 算數運算子Java
- 計算機基礎:位運算計算機
- 【java提高】(17)---Java 位運算子Java
- [java基礎]之 運算子Java
- Java基礎09:邏輯運算子、位運算子Java
- Java位運算小節Java
- Java中的位運算Java
- java基礎(四) java運算順序的深入解析Java
- [shell基礎]——算術運算
- Java程式設計基礎03——進位制運算&資料型別&變數Java程式設計資料型別變數
- java二進位制運算十進位制(精確運算)Java
- 演算法之位運算演算法
- Java 基礎-運算子Java
- == 運算子 - Java基礎Java
- 3.2 Tensorflow基礎運算
- Python基礎運算分享Python
- 演算法之美 : 位運算演算法
- 二進位制、位運算、位移運算
- (位運算)兩個字串的位運算字串
- 位運算
- 雲端計算運維-SRE基礎篇之安裝VMware運維
- NumPy 基礎 (二) - 陣列運算陣列
- javascript基礎(算數運算子)(八)JavaScript
- Python基礎教程04 運算Python
- 基礎演算法題——異或和之和(位運算、組合數)演算法
- Python基礎-不同型別之間的運算規則Python型別
- 零基礎學習 Python 之數字與運算Python
- Java基礎——邏輯運算子Java
- 理解位運算
- SQL位運算SQL
- [java基礎]之常量Java
- java基礎之XMLJavaXML
- 使用位運算進行加法運算
- pytorch基礎七(矩陣運算)PyTorch矩陣
- 05-JavaScript基礎-算數運算子JavaScript
- PHP基礎教程-10 算術運算子PHP
- ?Java基礎之Java列舉Java
- Python3 基礎學習之數值簡單運算Python