final byte x = 40; final byte y = -40; System.out.println(~x); // -41 System.out.println(~y); // 39 System.out.println(5 ^ 6); // 3 System.out.println(x ^ y); // -16 System.out.println(Integer.toBinaryString(x)); // 101000 System.out.println(Integer.toBinaryString(y)); // 11111111111111111111111111011000 System.out.println(Integer.toBinaryString(-16)); // 11111111111111111111111111110000 System.out.println(x << 2); // 160 System.out.println(x >> 2); // 10 System.out.println(x >>> 2); // 10 System.out.println(y << 2); // -160 System.out.println(y >> 2); // -10 System.out.println(y >>> 2); // 1073741814 System.out.println(y >>> 4); // 268435453
※這裡的符號都會轉換成二進制,可用 Integer.toBinaryString 或 Long.toBinaryString 查看,這兩個差在 32 位和64 位
40 的二進制:(前面沒有視同 0,總共 32 或 64 位) 10 1000
-40 的二進制:1111 1111 1111 1111 1111 1111 1101 1000
※正二進制轉負二進制
二進制取反 +1如:-40 的二進制就是 40 的二進制取反 +1
40 -> 10 1000 取反 --> 01 0111 加 1 -> (前面很多1) 01 1000
※負的二進制轉成 10 進制
取反後 +1 的 10 進制乘 -1※~ 取反(簡單公式就是 (x+1)*-1)
正數:二進制+1後轉10進制,然後乘-1
負數:二進制取反
.40 轉二進制 -> 10 1000 -> 10 1001 = 41 * -1 -> -41.-40 轉二進制 -> (前面很多1) 01 1000 取反->10 0111 = 39
※ ^ XOR 互相排斥,一正一反為 true,兩正兩反為 false
.5 ^ 65 -> 101
6-> 110
XOR 後,為 011 -> 3
.40 ^ -40
40 -> 101000
-40 -> 1111 1111 1111 1111 1111 1111 1101 1000
XOR 後,為 (前面很多1) 11 0000
驗證:
(前面很多1) 11 0000 取反 -> 1111 + 1 -> 1 0000 -> 16 * -1 = -16
※有兩個數想要互換,但不能用中間的 temp 變數,有以下兩種方法
一個數對另一個數互斥兩次,值不會變
var x = 66;
var y = 77;
x = x ^ y;
y = x ^ y;
x = x ^ y;
※要小心 x 和 y 的值一樣時,不能用這招,直接 return 即可
----------------------------------
先取得兩數的和再進行減法運算
var x = 66;
var y = 77;
x = x + y;
y = x - y;
x = x - y;
※要小心 x+y 超過類型的範圍就不行了
<< 2 往左二位,就相當於在最右邊增加 2 個 0
1010 0000 -> 2 的 7 次方 + 2 的 5 次方 -> 128 + 32 = 160
----------------------------------
先取得兩數的和再進行減法運算
var x = 66;
var y = 77;
x = x + y;
y = x - y;
x = x - y;
※要小心 x+y 超過類型的範圍就不行了
※ << 左移運算符
.40 -> 10 1000<< 2 往左二位,就相當於在最右邊增加 2 個 0
1010 0000 -> 2 的 7 次方 + 2 的 5 次方 -> 128 + 32 = 160
以十進位來說, <<2 就是乘 2 的 2 次方;<<3 就是乘 2 的 3 次方
.-40 -> (前面很多1) 01 1000 -> 0110 0000
驗證:
(前面很多1) 0110 0000 取反 -> 1001 1111 + 1 -> 1010 0000 -> 32 + 128 -> 160 * -1 = -160
可以背快速的用法:
例一:40 << 4:4 表示 2 的 4 次方,結果為 40 *16
例二:1 << 3:1 * 8
>> 2 往右二位,就相當於最右邊刪除 2 位,如果是正數,最左邊補 2 個 0
1010 = 10
.-40 -> (前面很多1) 01 1000 -> 0110 0000
驗證:
(前面很多1) 0110 0000 取反 -> 1001 1111 + 1 -> 1010 0000 -> 32 + 128 -> 160 * -1 = -160
可以背快速的用法:
例一:40 << 4:4 表示 2 的 4 次方,結果為 40 *16
例二:1 << 3:1 * 8
※ >> 右移運算符
.40 -> 10 1000>> 2 往右二位,就相當於最右邊刪除 2 位,如果是正數,最左邊補 2 個 0
1010 = 10
以十進位來說, >>2 就是除 2 的 2 次方;>>3 就是除 2 的 3 次方,如果有小數點都是無條件捨去
.-40 -> (前面很多1) 01 1000 -> (前面很多1) 0110,負數最左邊是補 1
驗證:
(前面很多1) 0110 取反 -> 1001 + 1 -> 1010 = 10 * -1 = -10
※左、右移運算符的應用可看這篇
※因為只有正數,左邊一定是 0,至於有幾個 0,要看 >>> 3 給 3 那就是 3 個 0;右邊的處理和 >> 一樣,刪 3 個最右邊的
※>> 右移運算符的負數是最左邊補 1,無符號是補 0,最左邊補0後,換算時就不是負的了,所以說只有正數,不用再取反+1了
-40 -> (前面很多1) 01 1000
.>>> 2,就相當於最右邊刪除 2 位,最左邊 2 個改 0
0011 1111 1111 1111 1111 1111 1111 0110
最左邊的 0 可以刪除
.>>> 4,就相當於最右邊刪除 4 位,最左邊 4 個改 0
0000 1111 1111 1111 1111 1111 1111 1101
最左邊的 0 可以刪除,最下面小算盤的圖就是省略了
從最右邊的 2的0次方到最左邊的 2 的 31 次方,一個一個加起來就是 10 進位了,但這個用人工算太累了,可用小算盤,如下:
int x = 40 << 2;
int o = 40;
o <<= 2; // o = o << 2;
此時 x 和 o 是一樣的意思,一定要分兩行,否則編譯錯誤,右移和無符號右移也是一樣,這在 jdk7 的 HashMap 原碼看到的
.-40 -> (前面很多1) 01 1000 -> (前面很多1) 0110,負數最左邊是補 1
驗證:
(前面很多1) 0110 取反 -> 1001 + 1 -> 1010 = 10 * -1 = -10
※左、右移運算符的應用可看這篇
※ >>> 無符號右移運算符 (就是只有正數,正數結果和 >> 一樣)
※就算宣告成 byte,結果還是 32 位,也不會報錯,可以正常使用※因為只有正數,左邊一定是 0,至於有幾個 0,要看 >>> 3 給 3 那就是 3 個 0;右邊的處理和 >> 一樣,刪 3 個最右邊的
※>> 右移運算符的負數是最左邊補 1,無符號是補 0,最左邊補0後,換算時就不是負的了,所以說只有正數,不用再取反+1了
-40 -> (前面很多1) 01 1000
.>>> 2,就相當於最右邊刪除 2 位,最左邊 2 個改 0
0011 1111 1111 1111 1111 1111 1111 0110
最左邊的 0 可以刪除
.>>> 4,就相當於最右邊刪除 4 位,最左邊 4 個改 0
0000 1111 1111 1111 1111 1111 1111 1101
最左邊的 0 可以刪除,最下面小算盤的圖就是省略了
從最右邊的 2的0次方到最左邊的 2 的 31 次方,一個一個加起來就是 10 進位了,但這個用人工算太累了,可用小算盤,如下:
※<<=、>>=、>>>=
int x = 40 << 2;
int o = 40;
o <<= 2; // o = o << 2;
此時 x 和 o 是一樣的意思,一定要分兩行,否則編譯錯誤,右移和無符號右移也是一樣,這在 jdk7 的 HashMap 原碼看到的
沒有留言:
張貼留言