位运算:
左移运算符m<<n表示把m左移n位。在左移n位的时候,最左边的n位将被丢弃,同时在最右边补上n个0
例如:
00001010<<2=00101000
10001010<<3=01010000
右移运算符与左移类似,但右移时处理最左边位时稍微复杂:
1、如果数字是一个无符号数值,则用0填补最左边的n位
2、如果数字是一个有符号数值,则用数字的符号填补最左边的n位
00001010>>2=00000010 正数,用0填补最左边的n位
10001010>>3=11110001 负数,用1填补最左边的n位
题目:
请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如:把9表示成二进制是1001,有2位是1.因此输入9,该函数输出2.
class Solution {
public:
int NumberOf1(int n) {
int count=0;
int flag=1;
while(flag)
{
if(n&flag)
count++;
flag=flag<<1;
}
return count;
}
};
问题:把整数右移一位和把整数除以2在数学上是等价的,那上面的代码中,可以把右移运算换成除以2吗?
答案:不可以,除法的运算效率比移位运算要低太多,在实际编程中尽可能使用移位运算符代替乘除法
还有避免程序陷入死循环,我们一般不直接移动整数,因为负数右移会陷入死循环。
我们可以采用使1移位,判断当前位是否是1,嗯,这真的是一个好方法。
下面还有更高效的方法
思路:
我们发现将一个整数减去1,再和原来的整数做位&运算,会把该整数最右边的1变成0。
因此一个整数的二进制中有多少1,它就可以做多少次这样的运算。
很多二进制问题都可以用这种方法计算。
举例:
1、1100,减一后为1011,1011&1100=1000
2、1000,减一后为0111,0111&1000=0000
代码:
class Solution {
public:
int NumberOf1(int n) {
int count=0;
while(n)
{
count++;
n=(n-1)&n;
}
return count;
}
};
相关题目:
1、用一条语句判断一个整数是不是2的整数次方。
一个整数如果是2的整数次方,那么他的二进制表示中有且只有一位是1,而其他所有位都是0.
根据前面的分析,把这个整数减去1之后再和它自己做与运算,这个整数中唯一的1就会变成0
2、输入两个整数 m和n, 计算需要改变m的二进制表示中的多少位才能得到n。
比如10的二进制表示为1010,13的二进制表示是1101,则需要改变1010中的3位才能得到1101.
思路:
第一步:求这两个数的异或
第二步:统计异或结果中1的位数,就又回到了前面的解法。
题目 二:
lintcode 给出两个整数a和b, 求他们的和, 但不能使用 + 等数学运算符。
思路:
考虑一个普通的加法计算:5+17=22
在十进制加法中可以分为如下3步进行:
1. 忽略进位,只做对应各位数字相加,得到12(个位上5+7=12,忽略进位,结果2);
2. 记录进位,上一步计算中只有个位数字相加有进位1,进位值为10;
3. 按照第1步中的方法将进位值与第1步结果相加,得到最终结果22。
下面考虑二进制数的情况(5=101,17=10001):
仍然分3步:
1. 忽略进位,对应各位数字相加,得到10100;
2. 记录进位,本例中只有最后一位相加时产生进位1,进位值为10(二进制);
3. 按照第1步中的方法将进位值与第1步结果相加,得到最终结果10110,正好是十进制数22的二进制表示。
接下来把上述二进制加法3步计算法用位运算替换:
第1步(忽略进位):0+0=0,0+1=1,1+0=0,1+1=0,典型的异或运算。
第2步:很明显,只有1+1会向前产生进位1,相对于这一数位的进位值为10,而10=(1&1)<<1。
第3步:将第1步和第2步得到的结果相加,其实又是在重复上述2步,直到不再产生进位为止。
源代码:
class Solution {
/*
* param a: The first integer
* param b: The second integer
* return: The sum of a and b
*/
public int aplusb(int a, int b) {
// write your code here, try to do it without arithmetic operators.
if(a==0) return b;
if(b==0) return a;
int sum,i;
i=a^b; //异或等价于两个数的相加,不考虑进位
sum=(a&b)<<1; //sum为进位的值
return aplusb(sum,i); //当进位sum为0时,返回i
}
};
参考:http://m.blog.youkuaiyun.com/article/details?id=50686724