位操作符(按位与,按位或,按位异或)

//整型变量的存储方式以及位运算均以补码方式进行:(正数原码反码补码均相同)

例如:-13

原码:10001101(原码的第一位表示符号位:1表示负数,0表示正数)

反码:11110010(符号位不变其他位取反)

补码:11110011(反码加一)

按位与:全1为1,有0则0

//把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0 。

//那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作。(可以用来计算2进制数中1的个数)

int Count(int n)
{
	int num = 0;
	while (n)
     {
		n &= (n - 1);
		num++;  
     }
	return num;
}

//与运算一用途:取一个数中指定位。找一个数,对应X要取的位,该数的对应位为1,其余位为零,此数与X进行“与运算”可以得到X中的指定位。例:设X=10101110,取X的后4位,用 X & 0000 1111 = 0000 1110 即可得到;还可用来取X的2、4、6位。

按位或:有1则1,全0为0

负数进行按位操作后得到的依然为补码:若要求其具体值还要转换成原码

int main()
{
	int a = 8;
    int b = -3;
	//	 8的原码:00000000000000000000000000001000
	//  -3的原码:10000000000000000000000000000011
	//		反码:11111111111111111111111111111100
	//		补码:11111111111111111111111111111101
	// 8的补码为:00000000000000000000000000001000
	//8 | -3得到:11111111111111111111111111111101(得到补码)
	//转换为原码:10000000000000000000000000000011(即为二进制的-3)
	int c = a | b;
	printf("%d\n", c);//输出-3
	return 0;
}

按位异或^:相同为0,相异为1

按位异或的3个特点:

(1) 任何数字异或它自己都等于0;

(2) 0异或任何数,等于任何数;

(3) 1异或任何数,等于取反任何数。

//进行异或运算时,当前位的两个二进制表示不同则为1相同则为0.该方法被广泛推广用来统计一个数的1的位数!

int main()
{
	int n = 0;
	int i = 0;
	int count = 0;
	scanf("%d", &n);
	for (i = 0; i < 32; i++)
	{
		if ((n ^ 1) == n - 1)//如果最后一位为1则异或1后小1;
			count++;
		n >>= 1;//右移一位
	}
	printf("%d\n", count);
	return 0;
}

//异或运算也可进行两个数的交换(不需要创建新的变量):

int main()
{
    int a = 3;
    int b = 5;
    printf("a=%d b=%d\n", a, b);
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    //类似于加减法中的:
    //a = a + b;   b = a - b; a = a -b;
    printf("a=%d b=%d\n", a, b);
    return 0;
}

利用异或的三个特点也可以解决某些问题:

如:1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;

正常解法这里就不说了,而且如果数字较大了话正常解法可能造成栈溢出,利用异或的特点1也可以迅速把它找出来。

int main()
{
	int arr[1001] = { 5 };
	int i = 0;
	int x = 0;//存储重复的数字
	for (i = 1; i < 1001; ++i)
		arr[i] = i;//得到1-1000且只含有一个重复数字的数组
	int j = 0;
	for (j = 0; j < 1001; j++)
		x = x^ arr[j];//首先对数组内每个元素异或一遍
	for (j = 1; j < 1001; j++)
		x = x ^ j;//对1-1000的数字异或一遍
	//这里相当于1-1000中除了重复那个其他数字均异或两遍,
	// 根据特点1、2可以得出x的值即为重复元素的值
	printf("%d\n", x);
}

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值