讀本文前請首先搞懂 “反碼”,“取反”,“按位取反(~)”,這3個概念是不一樣的。
取反:0變1,1變0
反碼:正數的反碼是其本身,對於負數其符號位不變其它各位取反(0變1,1變0)
按位取反(~): 這將是下面要討論的。
“~”運算符在c、c++、java、c#中都有,之前一直沒有遇到這個運算符。
要弄懂這個運算符的計算方法,首先必須明白二進制數在內存中的存放形式,二進制數在內存中是以補碼的形式存放的。
另外正數和負數的補碼不一樣,正數的補碼、反碼都是其本身,既:
正數9:
原碼為: 0000 1001
補碼為: 0000 1001
反碼為: 0000 1001
再例如: -2
求原碼: 1111 0010 (前面4個1表示符號位)
求反碼: 1111 1101 (符號位不變,其余各位求反)
求補碼: 1111 1110 (符號位不變,末位+1)
所以-2在內存中存放為: 1111 1110
-------------------------------------------------------------------------------------------------
弄懂了上述情況后,如何計算就好辦了
假設要對正數9按位取反——> (~9),計算步驟如下,
原碼為 0000 1001,
反碼為 0000 1001,
補碼為 0000 1001,
對其取反 1111 0110(符號位一起進行取反,這不是反碼更加不是最終結果,只是補碼的取反僅此而已)
我們還需要把他轉換成原碼,因為是負數所以進行負數補碼到原碼的逆運算
先減1得反碼: 1111 0101
取反得原碼:1111 1010,(反碼和原碼是一個相對的概念,對反碼取反就是原碼。取反過程符號位是不變的哦)
前面4個1是符號位,1是負數,既得十進制:-10
不知道說的明不明白,這里步驟就是:
1. 先對正數求補碼
2. 然后對補碼取反,包括符號位
3. 最后進行一個補碼求原碼的過程,一定要搞清概念啊。
-------------------------------------------------------------------------------------------------
下面我們再反推計算 (~ -10)
-10的原碼:1111 1010
-10的反碼:1111 0101 (符號位不變)
-10的補碼:1111 0110 (符號位不變,末位+1)
補碼取反:0000 1001 (符號位一起取反)
這是一個正數,那么我們對其求原碼就可得到最終結果?
因為正數的補碼,反碼,原碼都是一樣的 那我們的最終結果是 0000 1001 ,十進制是 9,這與我們前面推算出的結果吻合。
-------------------------------------------------------------------------------------------------
最后一個有趣的事實是:
1. 所有正整數的按位取反是其本身+1的負數
2. 所有負整數的按位取反是其本身+1的絕對值
3. 零的按位取反是 -1(0在數學界既不是正數也不是負數)
————————————————