给定一个数,将该数的某二进制位上置0、置1或取反。
输入格式:
第1行:输入一个十进制整数。(32位int取值范围,其二进制数补码表示)
第2行后:每行输入一个位操作运算要求。
格式:输入位操作运算类型(1表示置0,
2表示置1
,3表示按位取反
) 位数(从最低位向高位,范围从0~31
)
最终以键盘输入^Z
或 文件结束(EOF标志)。
输出格式:
输出位运算后的整数值。
输入样例:
在这里给出一组输入。例如:
-
3
-
1 0
-
1 1
-
2 3
-
3 1
-
3 2
-
2 0
输出样例:
在这里给出相应的输出。例如:
15
这一题相信大多数人是在学习位运算后写的,不过这题也可以通过位运算求解,不过相对于位运算代码量显得过多。
根据题目要求,要先输入一个整数,接着输入数字对整数的二进制进行操作。
置零:将某位数字变成0
置一:将某位数字变成1
取反:某位数字0变1,1变0
要解这道题目,对于数组来说,是不是要将输入的整数先转化为二进制存入数组,在对二进制的某位进行操作
而转化为二进制之前,我们首先要判断输入的整数是正是负数,毕竟二进制的转化规则不一样(转化规则这里不再介绍)
当n>=0时
注:求二进制的方法可以先取余2再整除2循环
当n<0时
在得到整数相应的二进制补码后,我们接下来要做的就是对二进制进行相应的操作
在完成输入的相应操作后,就要把变化后的二进制重新转化为一个新的整数了
注意:
这有两种不同的解法一种错误一种正确,我当时是第二种找不到错误后面问了老师才知道:
如果他从高位开始加,第一个数就是2的31次方-2147483648,因为补码最高位的权重是负的,int表示的范围是-2147483648到2147483647,2的31次方正好是2147483648,溢出1位,变成最小的负数-2147483648,但是如果低位开始加,不符合补码的真值计算过程,从高位开始加的话,由于一开始就溢出了,等于考虑到了最高位权重为负数的问题
最终代码如下:
#include <stdio.h>
#include <math.h>
int main()
{
int n,a,b,sum=0,number[32]={0},i,x=0;
scanf("%d",&n);
if(n>=0) //正数补码
{
number[0]=0;
for(i=31;i>=1;i--)
{
number[i]=n%2;
n=n/2;
}
}
else if(n<0) //负数原码
{
number[0]=1;
n=-n;
for(i=31;i>=1;i--)
{
number[i]=n%2;
n=n/2;
}
for(i=1;i<32;i++) //负数反码
{
if(number[i]==1)
{
number[i]=0;
}
else if(number[i]==0)
{
number[i]=1;
}
}
for(i=31;i>0;i--) //负数补码
{
if(number[i]==0)
{
number[i]=1;
break;
}
else
{
number[i]=0;
}
}
}
while (scanf("%d %d",&a,&b)!=EOF) //最终以键盘输入^Z 或 文件结束(EOF标志)
{
switch (a)
{
case 1:number[31-b]=0;break; //1代表所在位置置零
case 2:number[31-b]=1;break; //2代表所在位置置一
case 3: //3代表所在位置取反
if(number[31-b]==0)
{
number[31-b]=1;break;
}
else if(number[31-b]==1)
{
number[31-b]=0;break;
}
}
}
for(i=0;i<32;i++)
{
sum=sum+number[i]*pow(2,31-i);
}
printf("%d",sum);
return 0;
}