位運(yùn)算是把數(shù)字用二進(jìn)制表示之后,對每一位上0或者1的運(yùn)算。
負(fù)數(shù)的存儲
-
十進(jìn)制負(fù)數(shù)是以其補(bǔ)碼存儲在內(nèi)存上的。
驗(yàn)證:求-8在內(nèi)存上以二進(jìn)制形式1的個(gè)數(shù)
思路:拿變量,賦值為1,與-8的二進(jìn)制碼的每一位做與運(yùn)算,若與運(yùn)算結(jié)果為1,則該位為1.
結(jié)論:輸入-8,結(jié)果為29
分析:
? 在32位系統(tǒng)上,-8的存儲是以-8的補(bǔ)碼存儲在內(nèi)存中的,
? -8的源碼:1000 0000 0000 0000 0000 0000 0000 1000
? 取反,由于第一位是符號位,不用改變,得:1111 1111 1111 1111 1111 1111 1111 0111
? 補(bǔ)碼 = 反碼+1,得:1111 1111 1111 1111 1111 1111 1111 1000
? 得到1的數(shù)量正好為29,所以-8的補(bǔ)碼就是-8存儲在內(nèi)存上的二進(jìn)制碼
-
十六進(jìn)制,負(fù)數(shù)在內(nèi)存中存儲的是原碼
驗(yàn)證:對
int test = 0x80000001(對應(yīng)十進(jìn)制為-1)檢查其內(nèi)存上的1的個(gè)數(shù)結(jié)論:2
分析:
? 內(nèi)存上的原碼為 1000 0000 0000 0000 0000 0000 0000 0001
-
輸出0x80000000和0xFFFFFFFF
結(jié)論:
int i = 0x80000000后,輸出i,發(fā)現(xiàn)i=-(2^31)?
int i = 0xFFFFFFFF后,輸出i,發(fā)現(xiàn)i=-1分析:
? 0x800000000的二進(jìn)制原碼:1000 0000 0000 0000 0000 0000 0000 0000
? 在十六進(jìn)制中,負(fù)數(shù)的二進(jìn)制原碼的最高位是符號位,后面的31位為序號位,不是值位。
? 1后面的 000 0000 0000 0000 0000 0000 0000 0000,表示序號1,表示負(fù)數(shù)中從小到大的第一位。
? 由于int的最小值為-231,排在負(fù)數(shù)從小到大的序號1,所以輸出為-231。
? 再看0xFFFFFFFF,二進(jìn)制原碼:1111 1111 1111 1111 1111 1111 1111 1111
? 最高位為1,為負(fù)數(shù),序號位為 111 1111 1111 1111 1111 1111 1111 1111 = (231 - 1)
? 所以0xFFFFFFFF為負(fù)數(shù)從小到大第231 - 1位,即:-231 + 231 - 1 = -1,故輸出為-1
-
十進(jìn)制的補(bǔ)碼也符合 符號位 + 序號位 的原則
拿-8做例子:
-8的補(bǔ)碼:1111 1111 1111 1111 1111 1111 1111 1000,可以看到最高位為1
序號位:111 1111 1111 1111 1111 1111 1111 1000 = 231 - 8
則該補(bǔ)碼表示的值為 -231 + 231 - 8 = -8,符合
題目:請實(shí)現(xiàn)一個(gè)函數(shù),輸入一個(gè)整數(shù),輸出該數(shù)二進(jìn)制表示中1的個(gè)數(shù)。例如,把9表示成二進(jìn)制是1001,有2位是1,因此,如果輸入9,則該函數(shù)輸出2.
class Solution:
# 常規(guī)解法
def number_of_one(self, n):
count = 0
# 如果該整數(shù)是負(fù)數(shù),要把它和0xffffffff相與,消除負(fù)數(shù)的影響
# 因?yàn)槭M(jìn)制負(fù)數(shù)是以其補(bǔ)碼存儲在內(nèi)存上的
if n < 0:
n = n & 0xFFFFFFFF
while n:
n = (n - 1) & n
count += 1
return count
# 利用python特性
def number_of_one_a(self, n):
return bin(n & 0xFFFFFFFF).count("1")