C语言操作符的妙用

本章主要介绍如何用操作符进行解题(๑´ㅂ`๑)

目录

1.求一个整数的二进制中1出现的个数

2.求两个数的二进制中不同位的个数

3.一个数组中只有两个数字是出现一次,其他所有数字都出现了两次,写一个函数,找出这两个只出现一次的数字

4.写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换


1.求一个整数的二进制中1出现的个数

法一:

我们知道二进制的权值为2^(n-1),除以一个2^(n-1),小数点向前移动n-1位,因此我们可以对一个二进制数进行连续相除一个权值(2),判断余数的方法来求得整数的二进制中1出现的个数。

下面是代码实现:

#include<stdio.h>
int main()
{
	size_t n = 0;//(此处用无符号整型才能对负数进行计算)
	int count = 0;
	scanf("%zu", &n);
	while (n)
	{
		if (n % 2 == 1)
		{
			count++;
		}
		n /= 2;
	}
	printf("%d", count);
	return 0;
}

法二:

第二种方法就要用到操作符啦,在操作符中,>>操作符可以改变数的二进制位的最低位,而&1能得到数的二进制位的最低位,因此可以通过循环>>和&1的方法整数的二进制中1出现的个数。

下面是代码实现:

#include<stdio.h>
int main()
{
	int n = 0, count = 0;
	scanf("%d", &n);
	for (int i = 0; i < 32; i++)
	{
		if ((n >> i) & 1 == 1)
		{
			count++;
		}
	}
    printf("%d",count);
	return 0;
}

法三:

方法三用到一个结论:n&(n-1)可以得到一个去掉n的二进制数的最低位的数

代码实现如下:

#include<stdio.h>
int main()
{
	int n = 0, count = 0;
	scanf("%d", &n);
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	printf("%d", count);
	return 0;
}

2.求两个数的二进制中不同位的个数

可以将两个数异或起来,再求异或后数的二进制中一的个数

代码实现如下:

#include<stdio.h>
int main()
{
	int n1 = 0, n2 = 0, count = 0;
	scanf("%d %d", &n1, &n2);
	int n = n1 ^ n2;
	while (n & (n - 1))
	{
		count++;
	}
	printf("%d", count);
	return 0;
}

3.一个数组中只有两个数字是出现一次,其他所有数字都出现了两次,写一个函数,找出这两个只出现一次的数字

我们已经知道异或满足交换律,a^a=0,因此将数组中所用数字异或在一起可以得到两个只出现因此的数字,再找到异或后数的二进制中最低位1是第n位,根据数组中数的二进制位是否位1将数组分成两批(使只出现一次的数分进不同组里),每组当独异或即可得到两个只出现一次的数字

代码实现如下:

void findTwoNum(int arr[], int n, int* pnum1, int* pnum2)
{
	int i;
	int sum = 0;
	​
		for (i = 0; i < 9; i++)
		{
			sum ^= arr[i];
		} //先找到两个数互相异或的结果
	​
		int pos;
	for (i = 0; i < 32; i++)
	{
		if (sum & 1 << i)
		{
			pos = i;
			break;
		}
	} //再找到有分歧的一位。在这一位上,两个数一定是一个1一个0
	​
		* pnum1 = *pnum2 = 0;
	for (i = 0; i < 10; i++)
	{
		if (arr[i] & 1 << pos)
		{
			*pnum1 ^= arr[i]; //这一位是1的,放在数1里
		}
		else
		{
			*pnum2 ^= arr[i]; //这一位是0的,放在数2里
		}
	}
}

4.写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换

交换奇数位和偶数位可以分别拿出奇偶位再移位相加(奇数位拿出,那就是要&上010101010101……(0x55555555),偶数位拿出,就是要&上101010101010……(0xaaaaaaa) )

代码实现如下:

#define(SwapIntBit(n) (((n) & 0x55555555) << 1 | ((n) & 0xaaaaaaaa) >> 1)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

记得开心一点啊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值