关于二进制位操作的一些面试题

题目1:

1、不能创建临时变量,实现两个数的交换。

2、思路

1)常规方法,创建临时变量(很简单)

int main()
{
	int a = 1;
	int b = 2;
	printf("交换前:a = %d  b = %d\n", a, b);
	int tmp = 0;
	tmp = a;
	a = b;
	b = tmp;
	printf("交换后:a = %d  b = %d\n", a, b);
	return 0;
}

1
2)利用加法求和来做(缺点:在数据溢出时,结果错误)

int main()
{
	int a = 1;
	int b = 2;
	printf("交换前:a = %d  b = %d\n", a, b);
	a = a + b;
	b = a - b;
	a = a - b;
	printf("交换后:a = %d  b = %d\n", a, b);
	return 0;
}

1
3)**第三种方法是:利用异或来做,这个是很多人想不到的,这不一定,它的原理是:相同为0,相异为1。可以得出 a^a = 0 a^0 = a;**靠这两个关系式来做!

int main()
{
	int a = 1;
	int b = 2;
	printf("交换前:a = %d  b = %d\n", a, b);
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("交换后:a = %d  b = %d\n", a, b);
	return 0;
}

1

题目2:

3、求一个整数存储在内存中的二进制中1的个数

 *突然想到一个问题,特别重要!!!
 int a = 1;(在内存中补码存储)
 int b =-1;(在内存中补码存储)
 unsigned int c = 10;
 unsigned int d = -10;这两个在内存中怎么存储呢?验证一下!!!

1
1

数据在内存中怎样存储的跟数据类型无关,跟它本身是正数还是负数有关,在printf通过格式控制打印的时候,这时候是要求打印的什么数,根据要求转换在内存中看到的数!!!
有了这些基础来搞这道题!!!

4、思路

 1)既然它是求得在内存中的二进制数的1的个数,那么可以把这个数a%2判断是不是1,a/2去掉一位,就可以计算,但是有个问题,你想一下,如果这个数是正数,符号位是0,不是1,自然可以这样算,如果是负数呢?就不能这样算了,一个是符号位是1,需要统计进去,还有一个问题,与2的余数就不是0或1了,不能计算,基于上面的这几种情况,即使是正数,也不合适,只是结果对了,因为在正数中,把符号位没有统计(虽然它是0,统计不统计一样),负数压根不合适,这种情况的解决办法就是转成无符号数来搞,就可以了,因为重要一个确定了,那么在内存中存的形式是一定的,当转成无符号数时,二进制全部是数值位,就可以这样计算了!!!这种方法没有你想象的那么简单!!!

int CountOnebit(unsigned int num)
{
	int count = 0;
	while (num)
	{
		if (num%2 == 1) {
			count++;
		}
		num /= 2;
	}
	return count;
}

int main()
{
	int nums = CountOnebit(-10);
	printf("%d\n", nums);
	return 0;
}

在这里插入图片描述
  2)第二种方法是用&操作符来做,这个&(按位操作符)直接面对的是二进制,没有那么多弯弯绕绕!可以直接做,右移一位,判断一位!

int CountOnebit(unsigned int num)
{
	int count = 0;
	for (int i = 0; i < 32; i++)
	{
		int a = num>> i;
		//1
		//00000000 00000000 0000000 0000001 1的特殊性来做
		if (a & 1 == 1)
		{
			count++;
		}
	}
	return count;
}

int main()
{
	int nums = CountOnebit(-10);
	printf("%d\n", nums);
	return 0;
}

  3)第三种方法跟第二种差不多,因为二进制只有0和1,你想一下,a = -10,b = -10-1,在a的基础上-1,是不是对应的补码差1,那么a和b对应的二进制的最后1位或2位肯定不一样,则可以统计&操作符,来使最后的一位或两位成为0,则去除了一个1,这样通过不断去除1的方式,来统计二进制中的1.

int CountOneBit(int n)
{
	int count = 0;
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	return count;
}
int main()
{
	int n = CountOneBit(n);
	return 0;
}

题目3:

5、编写代码将13的二进制序列的第5位修改为1,然后再修改回0.

  00000000 00000000 00000000 00001101
  |
  00000000 00000000 00000000 00010000
  00000000 00000000 00000000 00011101
可以看出要把二进制的哪一位置1,就是要给哪一位或1的问题,其余位不变,其实就值移动1的问题。
  00000000 00000000 00000000 00011101
  &
  11111111 11111111 11111111 11101111
  00000000 00000000 00000000 00001101
可以看出,要把哪一位置0,其实就是其余位&1,这一位&0的过程。这儿有一点小技巧,因为直接得到&的这个数不好弄,但它的反面好弄,在取反即可!

int main()
{
	int a = 13;
	//将a的第5位置1;
	a = a | (a << 4);
	printf("a = %d\n", a);
	//将a的第5位置0;
	//下面的处理注意一下
	//直接不好弄,取反即可
	a = a & (~(a << 4));
	printf("a = %d\n", a);
	return 0;
}

完结!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值