位运算符+位运算的应用

目录

一:位运算符

1:按位与&

 2:按位或|

 3:按位取反~

 4:按位异或

 5:移位

1.左移<<:

2.右移>>:

6:码

1.原码:

2:反码:

3:补码:

二:位运算实战

1:判断奇偶数

2:判断二进制位是1还是0

3:交换两个数的值(不使用第三个变量无加减乘除)

4:找出那个落单的数

附加:力扣题:只出现了一次的数字

5:二进制中1的个数

6:2的幂

7:颠倒二进制位


一:位运算符

1:按位与&

类似与数学里的交集,只有两个数都是1时,按位与的结果才是1,否则是0

例如 : 

 2:按位或|

相当于数学里的并集,只有两者中有一个为1,那么它们或的按位或的结果就是1

例如:

 3:按位取反~

即0取反后变成1,1取反后变成0

例如:

 4:按位异或

相同的数字异或为0,相异的数字异或为1

例如:

 5:移位

移位能使程序的运行效率更高,可代替乘除法

1.左移<<:

最左侧不要了,最右侧直接补0;(左移相当于乘法,如左移1位,相当于乘以2的1次方)

2.右移>>:

最右侧不要了,最左侧直接补0;(右移相当于除法,如右移1位,相当于除以2的1次方)

6:码

1.原码:

将这个数字按照正负数的形式翻译成二进制

2:反码:

正数的反码是它本身

负数的反码是(除了符号位不变)其他的位置的是原码取反

3:补码:

正数的补码是它本身

负数的补码是它的反码+1

例如:

    int a = 10;  //整型a是4个字节,32位
 
	// 00000000 00000000 00000000 00001010 - 原码
	// 00000000 00000000 00000000 00001010 - 反码
	// 00000000 00000000 00000000 00001010 - 补码
 
	int b = -10;
 
	// 10000000 00000000 00000000 00001010 - 原码
	// 11111111 11111111 11111111 11110101 - 反码
	// 11111111 11111111 11111111 11110110 - 补码

在进行位运算时:是以补码的形式进行计算的,输出的结果是补码进一步转换成原码输出的


二:位运算实战

1:判断奇偶数

题目:输入一个数字,判断它是奇数还是偶数,用位运算来实现

解析:我们首先要知道,我们输入的数字是10进制,在计算机中是2进制,那么2进制转10进制是该位数字*2^(n-1)   n表示的是它在第几个位置

比如:

 我们发现只有最后有机会去决定正负,因为是1或者0乘2的0次方(也就是1)

如果最后一位是1,那么它就是奇数

如果最后一位是0,那么它就是偶数

现在的问题就转变为:如何知道最后一位是1,还是0?

想想我们之前的位运算符,这就是我们的武器= = :答案是让1去&这个数num

如果是答案是1,那么我们就可以知道,num这个数的第一位就是1

如果答案是0,那么我们就可以知道,num这个数的第一位就是0

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int num = 0;
	scanf("%d", &num);
	if ((num & 1) == 1)
	{
		printf("%d是奇数", num);
	}
	else
	{
		printf("%d是偶数", num);
	}

	return 0;
}

2:判断二进制位是1还是0

题目:给出一个数,让你判断它的某一位是0还是1

比如这里这个数我们定为76,然后我们要判断这个数的第3位是0还是1

思路解析:

其实也还是很简单,我们题目既然要我们求的是第3位,那么我们就只需把这个数字右移2位,然后用1&这个数字就可以了

如果答案是1,那么这个数字的第三位就是1,反之则为0

代码实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int num = 76;
	int temp = num;
	int k = 3;
	num = num >> (k - 1);
	if ((num & 1) == 1)
	{
		printf("%d的第%d个位置的数字是1", temp, k);
	}
	else
	{
		printf("%d的第%d个位置的数字是0", temp, k);
	}

	return 0;
}

3:交换两个数的值(不使用第三个变量无加减乘除)

这个方法比较难想,先上答案把

 想不明白的同学将a,b代进去就可以理解了= =

异或就像消消乐,只有偶数倍个数的数字出现都为被消掉


4:找出那个落单的数

一个数组中除了某一个元素中之外,其他的元素都出现了两次,写程序找出这份只出现一次的数字

看到有两次,找一个,马上就要想到异或,直接消消乐

#include<stdio.h>
int main()
{
	int arr[] = { 1,1,2,3,3,4,4,5,5 };
	int n = sizeof(arr) / sizeof(arr[0]);
	int x = 0;
	for (int i = 0; i < n; i++)
	{
		x = x ^ arr[i];
	}
	printf("%d\n", x);
	return 0;
}

附加:力扣题:只出现了一次的数字

 

 代码实现:

int singleNumber(int* nums, int numsSize)
{
	int ret = 0;
	for (int i = 0; i < numsSize; i++)
	{
		ret = ret ^ nums[i];
	}
	return ret;
}

5:二进制中1的个数

 思路解析:

我们在前面已经知道了如何判断第一个位的数字是1还是0,那么我们只需在一个循环里,一次移动移位,共32次,如果遇到了为1,那么就让计数器++,返回计数器即可

int hammingWeight(uint32_t n) 
{
	int result = 0;
	for (int i = 1; i <= 32; i++)
	{
		if (n & 1 == 1)
		{
			result++;
		}
		n >>= 1;
	}
	return result;
}

6:2的幂

 思路解析:

先自己用二进制表达一下,2的幂,2^1,2^2,2^3

你会发现它们的共同点是,最高位是1,其余为都是0

这个时候有一个特别神的方法:将n&(n-1),如果为0,则说明n是2的幂,反之不是

画图理解:

 但是还得有一个条件约束,就是n>0,因为这个题目条件其实要求的是n为正数的情况= =

bool isPowerOfTwo(int n){
    return (n>0) && (n&(n-1))==0;
}

一行足以

7:颠倒二进制位

 思路解析:

开一个新的数ret,将它+n这个数二进制位的第一个数,并让ret左移1,让n右移1,循环32次,这样就实现了倒转

代码实现:

uint32_t reverseBits(uint32_t n) {
    uint32_t ret = 0;
    for (int i = 0; i < 32; i++) 
    {
        ret <<= 1;
        ret += (n & 1);
        n >>= 1;
    }
    return ret;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值