题目:
请实现一个函数,计算一个整数二进制表示中1的个数,例如:把9表示成二进制是1001,有2位是1
方案一
判断该数最后一位是不是1,然后把该数右移一位;这样每次移动一位直到这个数变为0为止。但是该思路有个问题就是该数是负数时,会变成死循环,因为负数的最高位是1,即使右移之后,为了保证该数还是负数,仍会把最高位置为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)//死循环
方案二
对方案一会产生死循环的一种改良,把该数首先与1(即为flag)做&
运算判断判断最低位是否为1,然后把flag左移一位,判断第二位是否为1,直到flag为0。在4字节的Int类型里也就是移动32次。
extension Int {
var binaryOneNumber : Int {
var flag = 1
var count = 0
while flag != 0 {
if flag & self > 0{
count += 1
}
flag = flag << 1
}
//如果是负数的话,最高位会统计不上,这里在加1
if self < 0 {
count += 1
}
return count
}
}
print(0.binaryOneNumber) //输出0
print(9.binaryOneNumber) //输出2
//这里输出63是正确的,mac os里Int是64位的,在64位里-9的补码是
//1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0111
print((-9).binaryOneNumber)//输出63
方案三
在二进制中,把一个整数减去1之后再和原来的整数做&
运算,得到的结果相当于把该整数的二进制表示中最右边的1变成0。因此可以每次都把n & (n - 1)
的结果赋值为n,直到n为0结束。
extension Int {
var binaryOneNumber : Int {
var tmp = self
var count = 0
while tmp != 0 {
//这里减一,不能直接用-,有可能会有溢出错误的
//因为负数的最大值的补码形式是1000 0000...,此时在进行减1,就会有溢出错误
tmp = tmp & (tmp &- 1)
count += 1
}
return count
}
}
print(0.binaryOneNumber) //输出0
print(9.binaryOneNumber) //输出2
print((-9).binaryOneNumber)//输出63
print((-1).binaryOneNumber)//输出64
网友评论