强大的位运算 (算法必备)

本文详细介绍了C语言的位运算符,包括按位与(&)、按位或(|)、异或(^)、取反(~)、左移(<<)和右移(>>)。重点讲解了它们的运算规则、实际应用场景,如消除尾一、奇偶性判断和数据交换,以及如何通过位运算优化代码效率。
摘要由CSDN通过智能技术生成

C语言提供了六种位运算符: & 按位与,| 按位或,^ 按位异或,~ 取反,<< 左移,>> 右移。下面让我们来一一了解。这次就精炼一点,侧重于用法,不过多的去关注一些花里胡哨的东西了。


位运算运算规则:

a

b

a&b

a|b

a^b

~a

a<<b

a>>b

0

0

0

0

0

1

a二进制形式左

a二进制形式右

0

1

0

1

1

1

移b位

移b位

1

0

0

1

1

0

相当于a乘 2的b

相当于a除以 2的b

1

1

1

1

0

0

次方

次方


一,&按位与运算

按位与是双位运算符,只有对应的两个二进制都为1时,结果为才为1,否则为0。参与运算的数以补码的方式出现。

用法:

1,消除尾一

我第一次见到这种用法是在一个蓝桥杯的题里,要求把一个二进制数最右边的连续的1全部变成0,如果最后一位是0,则原数字保持不变。

输入:

00000000000000000000000001100111

输出:

0000000000000000000000001100000

 这道选择题的答案是 x=x&(x+1) 。为了便于学习,我把整段代码也放在这。

#include<iostream>
using namespace std;
void f(int x)
{
	for (int i = 0; i < 32; i++) {
		printf("%d", (x >> (31 - i)) & 1);  //将十进制转化成二进制输出
	}
	printf("   ");

	x = x & (x + 1);  //将尾部连续的1消掉

	for (int i = 0; i < 32; i++) {
		printf("%d", (x >> (31 - i)) & 1);
	}
	printf("\n");
}
int main() {
	f(103);
	f(12);
	return 0;
}

2,判断奇偶

学过一个星期计算机的应该都知道,判断奇偶我们可以用取余运算符,但这时一个装逼的机会来了,我们可以回归计算机的底层,用&运算符来判断,来看代码。

#include<iostream>
using namespace std;
void check(int x)
{
	if (x & 1 == 1) {                  //按位与运算符判断奇偶
		cout << x << "是奇数" << endl;
	}
	else {
		cout << x << "是偶数" << endl;
	}
}
int main() {
	check(103);
	check(12);
	return 0;
}


二,| 按位或运算符

对应的二进位有一个位1时,结果位就为1。参与运算的数以补码的方式出现。

 举例: 

     00001001

|    00000101

---------------------

     00001101           即9|5=13。

这个运算符不常用,大家知道怎么运算就行,有兴趣的话可以查下资料。


三,^异或运算符

对应的二进位不相等时,结果为1,相等时,结果为0。

 用法:

交换两个数

这个作用比较大,因为用&运算符进行交换时,可以避免另外开辟空间来存储临时变量,这样也可以加快程序的速度,在算法上是比较提倡的。来看代码,里面写有详细注释。

#include<iostream>
using namespace std;
int main() {
	int a = 12, b = 56;

	a = a ^ b;   

	b = a ^ b;   //此时开始交换,将上式代入,相当于 b=a^b^b
	             //两个相同的数异或之后等于0,任何数与0异或等于其本身
	            //即b^b=0  ,  a^0 =a  ,此时a赋值给b
	a = a ^ b;   //将上一个式子代入 a=a^a^b
	             //a^a=0 , 0^b=b , 此时b的值赋给a

	cout << a <<"   " << b << endl;
	return 0;
}

四,~求反运算符 

求反运算符~为单目运算符,具有有结合性。其功能是对参与运算的数的各二进制位按位求反。

例如,~9的运算为~(0000000000001001),结果为 1111111111110110。


五,<<左移运算符

左移运算符是双目运算符,其功能是把“<<”左边的运算数的各二进位全部左移若干位,由运算符右边的数指定移动的位数,高位丢弃,低位补0。

用法:

 在数字没有溢出的前提下,对于正数和负数,左移一位相当于乘以2的1次,左移n位相当于乘以2的n次方。

左移运算比乘法快,可以用来优化代码。


六,>>右移运算符 

右移运算符是双目运算符,其功能是把运算符左边的运算数的各二进位全部右移若干位,运算符右边的数指定右移的位数。

 对于有符号的数,在右移时,符号位将随之移动。当为正数时,最高位补0,为负数时,符号位为1,最高位补1或是补0取决于编译系统的规定,大多数系统规定补1。

用法: 

和左移运算差不多,不过,右移一位表示除以2的一次方,右移n位表示除以2的n次方

同样可以用来优化代码


 目前我只总结了这些,随着算法学习的深入,之后应该会接触到更多的,到时候我会再进行补充。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodingCaius

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值