位操作符、移位操作符与位运算

位运算是把数字用二进制表示之后,对每一位上0或者1的运算。二进制及其位运算是现代计算机学科的基石,很多底层的技术也都离不开位运算,由于在我们日常生活中习惯了十进制,很多人看到二进制以及位运算都感到很难适应,接下来我们一起讨论一下移位操作符和位操作符以及位运算。

移位操作符

<< 左移操作符
在这里插入图片描述
>> 右移操作符
在这里插入图片描述

位操作符

& 按位与(二进制位)
| 按位或(二进制位)
^ 按位异或 相同为0相异 相异为1(二进制位)
注意区分逻辑与 &&(两真为1) 和逻辑或 ||(两假为0)

我们来看一道面试题(360):

#include <stdio.h>
int main()
{
	int i = 0,a = 0,b = 2,c = 3,d = 4;
	i = a++ && ++b && d++;
	//i = a++ || ++b || d++;
	printf("a=%d b=%d c=%d d=%d",a,b,c,d);
	return 0;
}

运行结果:

a=1 b=2 c=3 d=4

解析:
逻辑&&运算一旦左边为假后面便不再运算,本题a=0先发生作用使&&左边为假b,c,d的值不再变化,a再++变为1 输出。

位运算

其实二进制的位运算并不是很难掌握,因为位运算总共只有上述的五种,&,|,^,>>,<<。
注:下表的0 1均在二进制环境中
在这里插入图片描述
我们通过几个例子来熟悉掌握位运算吧!

题目:实现一个函数,输入一个整数,输出该数二进制表示中1的个数(剑指offer面试题)

解法一:(可能引起死循环的解法)

  • 基本思路:先将这个数二进制表中最后一位与1做&运算判断最后一位的值,然后再将这个数右移一位即可判断倒数第二位的值,以此类推,定义计数器count,&的结果为1则count++,直到这个数为0跳出while循环,输出count。
int Count(int n)
{
	int count = 0;
	while (n)
	{
		if (n & 1)
			count++;
			
		n = n >> 1;
	}
	return count;
}

注意:虽然右移一位和÷2在数学上等价,但除法效率比右移操作低得多,所以不能更换右移操作为除法。
缺陷:如果输入负数,右移过程中高位始终补1,最终陷入死循环。

解法二:(常规解法)

  • 基本思路:为了避免死循环可以不移动输入的n,去左移与n进行&运算的1,直到flag的二进制变为全0,跳出while,输出count。
int Count(int n)
{
	int count = 0;
	int flag = 1;
	while (flag)
	{
		if (n & flag)
			count++;
			
		flag = flag << 1;
	}
	return count;
}

缺陷:不论1的个数为多少,该程序都会循环32次

解法三:(给面试官带来惊喜的解法)

  • 基本思路:把一个整数n减去1,都是把它二进制序列最右边的1变为0,而左边的其他位保持不变,右边的0变为1。再将n和n-1做&运算,下一个1之前的二进制序列全都变为0。n中有几个1就进行几次&运算,大大提高了程序的效率。
int Count(int n)
{
	int count = 0;
	while (n)
	{
		n = n&(n - 1);//每次&都是最后一个为1的位变为0
		count++;
	}
	return count;
}

亮点:有多少个1就循环多少次
在这里插入图片描述

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值