題目:
請(qǐng)實(shí)現(xiàn)一個(gè)函數(shù),計(jì)算一個(gè)整數(shù)二進(jìn)制表示中1的個(gè)數(shù),例如:把9表示成二進(jìn)制是1001,有2位是1
方案一
判斷該數(shù)最后一位是不是1,然后把該數(shù)右移一位;這樣每次移動(dòng)一位直到這個(gè)數(shù)變?yōu)?為止。但是該思路有個(gè)問(wèn)題就是該數(shù)是負(fù)數(shù)時(shí),會(huì)變成死循環(huán),因?yàn)樨?fù)數(shù)的最高位是1,即使右移之后,為了保證該數(shù)還是負(fù)數(shù),仍會(huì)把最高位置為1。
extension Int {
var binaryOneNumber : Int {
var tmp = self
var count = 0
while tmp != 0 {
if tmp & 1 == 1{
count += 1
}
tmp = tmp >> 1
}
return count
}
}
print(0.binaryOneNumber) //輸出0
print(9.binaryOneNumber) //輸出2
print((-9).binaryOneNumber)//死循環(huán)
方案二
對(duì)方案一會(huì)產(chǎn)生死循環(huán)的一種改良,把該數(shù)首先與1(即為flag)做&運(yùn)算判斷判斷最低位是否為1,然后把flag左移一位,判斷第二位是否為1,直到flag為0。在4字節(jié)的Int類型里也就是移動(dòng)32次。
extension Int {
var binaryOneNumber : Int {
var flag = 1
var count = 0
while flag != 0 {
if flag & self > 0{
count += 1
}
flag = flag << 1
}
//如果是負(fù)數(shù)的話,最高位會(huì)統(tǒng)計(jì)不上,這里在加1
if self < 0 {
count += 1
}
return count
}
}
print(0.binaryOneNumber) //輸出0
print(9.binaryOneNumber) //輸出2
//這里輸出63是正確的,mac os里Int是64位的,在64位里-9的補(bǔ)碼是
//1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0111
print((-9).binaryOneNumber)//輸出63
方案三
在二進(jìn)制中,把一個(gè)整數(shù)減去1之后再和原來(lái)的整數(shù)做&運(yùn)算,得到的結(jié)果相當(dāng)于把該整數(shù)的二進(jìn)制表示中最右邊的1變成0。因此可以每次都把n & (n - 1)的結(jié)果賦值為n,直到n為0結(jié)束。
extension Int {
var binaryOneNumber : Int {
var tmp = self
var count = 0
while tmp != 0 {
//這里減一,不能直接用-,有可能會(huì)有溢出錯(cuò)誤的
//因?yàn)樨?fù)數(shù)的最大值的補(bǔ)碼形式是1000 0000...,此時(shí)在進(jìn)行減1,就會(huì)有溢出錯(cuò)誤
tmp = tmp & (tmp &- 1)
count += 1
}
return count
}
}
print(0.binaryOneNumber) //輸出0
print(9.binaryOneNumber) //輸出2
print((-9).binaryOneNumber)//輸出63
print((-1).binaryOneNumber)//輸出64