浅谈位运算

\[VC总结系列——位运算 \]


目录

零. 附录(先看附录)

一.与“&”运算

二.或“|”运算

三.异或“^”运算

四.取反“~”运算

五.左移“<<”运算

六.右移“>>”运算

七.拓展延伸

八.更新日志


零.附录

1). 十进制转二进制//位运算主要需要的转换

#include<cstdio>
int a[1005];
int main() {
   int n,i,j=0;
   scanf("%d",&n);
   i=n;
   while(i){
        a[j]=i%2;
        i/=2;
        j++;
   }
   for(i=j-1;i>=0;i--){
   	printf("%d",a[i]);
   }
  return 0;
}
Code from a long time ago.

2). 十进制转换成其它进制

#include<cstdio>
int a[1000];
int main() {
   int n,m,i,j=0;
   scanf("%d %d",&n,&m);
   	i=n;
    while(i)
	{
       a[j]=i%m;
       i/=m;
       j++;
    }  	
   printf("(%d)10=(",n);
   for(i=j-1;i>=0;i--)
   {
   	  if(a[i]>=10)
   	  {
   	  	printf("%c",char(a[i]+55));
	  }
		 else
		 {
		 	printf("%d",a[i]);
		 }
   }
   printf(")%d",m);
  return 0;
}	
The code is a bit old.

3). 其它进制转换成十进制

#include<cstdio>
#include<cmath>
#include<cstring>
char b[100];
long int c;
int main(){
	int a,i,j,n=0;
	scanf("%d",&a);
	for(i=-1;b[i]!='\n';i++)
	{
		scanf("%s",b);
		if(b[i]=getchar())break;
	} 
	n=strlen(b);
	printf("(");
	for(i=n-1,j=0;i>=0,j<n;i--,j++)
	{
		if(b[i]>='0'&&b[i]<='9')
		{
		    c+=pow(a,j)*(b[i]-'0');
		}
		else if(b[i]>='A'&&b[i]<='F')
		{
			c+=pow(a,j)*(b[i]-'7');
		}
	}
	for(i=0;i<n;i++)
	{
		printf("%c",b[i]);
	}
	printf(")%d=(%ld)10",a,c);
	return 0;
}
The code......

然后良心VC推荐一在线工具进制转换器

附录End.


一.与“&”运算:

1). 表达式:a&b

2). 表达式意思:整数a与整数b做“与&”运算

3). 定义:如果两个相应的二进制位数字都为1,则该位的结果为 1(true);否则为 0(false)。

4). 例子e.g.:66&88结果为64,because 66对应的二进制是01000010,88对应的二进制是01011000,所以就是01000010 and 01011000做运算得01000000,01000000转换成整数就是64。

5). code(代码中也有一些解释):

#include <cstdio>
int a , b;
int tft(int n) {//进制转换 
   	int i , j = 0 , a[100001];
   	i = n;
   	while(i) {
        a[j] = i % 2;
        i /= 2;
        j++ ;
   	}
   	if (j-1 < 8) {//∵位运算是8位二进制补码 
   		for (int k=1; k<=8-(j-1); k++ ) {
   			printf("0");//前面填零方便观看 
		}
	}
   	for(i=j-1; i>=0; i--){
		printf("%d",a[i]);//输出转换后的
    }
    printf(" -> %d",n);
}
int main(void) {
    scanf("%d %d",&a,&b);
	tft(a);//a数转换后的输出 
	printf("\n");
	tft(b);//b数转换后的输出 
	printf("\n");
	tft(a & b);
	printf("(这里的%d指%d&%d算出的值)\n",a&b,a,b);
	printf("%d",a&b);//进行与运算 
}
/*
test.in : 3 5
test.out: 
00000011 -> 3
00000101 -> 5
00000001 -> 1(这里的1指3&5算出的值)
1
*/

与“&”运算End.


二.或“|”运算

1). 表达式:a|b

2). 表达式意思:整数a与整数b做“或|”运算

3). 定义:如果两个相应的二进制位数字有一个为1,则该位的结果为 1(true);否则为 0(false)。

4). 例子e.g.:66|88结果为90,because 66对应的二进制是01000010,88对应的二进制是01011000,所以就是01000010 and 01011000做运算得01011010,01011010转换成整数就是90。

5). code(代码中也有一些解释):

/*
00000011   3
00011011   27
->结果 
00011011   27
*/
#include <cstdio>
int a , b;
int tft(int n) {//进制转换 
	int i , j = 0 , a[100001];
	i = n;
	while(i) {
	    a[j] = i % 2;
    	i /= 2;
        j++ ;
	}
	if (j-1 < 8) {//∵位运算是8位二进制补码 
		for (int k=1; k<=8-(j-1); k++ ) {
			printf("0");//前面填零方便观看 
		}
	}
	for(i=j-1; i>=0; i--){
		printf("%d",a[i]);//输出转换后的
    }
    printf(" -> %d",n);
}
int main(void) {
    scanf("%d %d",&a,&b);
	tft(a);//a数转换后的输出 
	printf("\n");
	tft(b);//b数转换后的输出 
	printf("\n");
	tft(a | b);
	printf("(这里的%d指%d|%d算出的值)\n",a|b,a,b);
	printf("%d",a|b);//进行或运算 
}
/*
test1.in : 3 5
test1.out:
00000011 -> 3
00000101 -> 5
00000111 -> 7(这里的7指3|5算出的值)
7

test2.in : 48 15
test2.out:
00110000 -> 48
00001111 -> 15
00111111 -> 63(这里的63指48|15算出的值)
63 
*/

或“|”运算End.


三.异或“^”运算

1). 表达式:a^b

2). 表达式意思:整数a与整数b做“异或^”运算

3). 定义:如果两个相应的二进制位数字不相同,则该位的结果为 1(true);否则为 0(false)。

4). 例子e.g.:66^88结果为26,because 66对应的二进制是01000010,88对应的二进制是01011000,所以就是01000010 and 01011000做运算得00011010,00011010转换成整数就是26。

5). code(代码中也有一些解释):

/*
00000001    1
00001111    15
->结果
00001110    14
*/
#include <cstdio>
int a , b;
int tft(int n) {//进制转换 
   	int i , j = 0 , a[100001];
   	i = n;
   	while(i) {
        a[j] = i % 2;
        i /= 2;
        j++ ;
   	}
   	if (j-1 < 8) {//∵位运算是8位二进制补码 
   		for (int k=1; k<=8-(j-1); k++ ) {
   			printf("0");//前面填零方便观看 
		}
	}
   	for(i=j-1; i>=0; i--){
		printf("%d",a[i]);//输出转换后的
    }
    printf(" -> %d",n);
}
int main(void) {
    scanf("%d %d",&a,&b);
	tft(a);//a数转换后的输出 
	printf("\n");
	tft(b);//b数转换后的输出 
	printf("\n");
	tft(a ^ b);
	printf("(这里的%d指%d^%d算出的值)\n",a^b,a,b);
	printf("%d",a^b);//进行异或运算 
}
/*
test1.in : 3 5
test1.out:
00000011 -> 3
00000101 -> 5
00000110 -> 6(这里的6指3^5算出的值)
6

test2.in : 52 15
test2.out:
00110100 -> 52
00001111 -> 15
00111011 -> 59(这里的59指52^15算出的值)
59
*/

或“|”运算End.


四.取反“~”运算

1). 表达式:~a

2). 表达式意思:整数a做“或~”运算

3). 定义:将整数a的各个二进制位都取反,相当于1变成0,0变成1。

4). 例子e.g.:~9结果为-10,because 9对应的二进制是00001001,对00001001进行取反得11110110,这个11110110为补码,而反码等于补码减一,所以反码为11110101,再符号位不变,其他位取反得10001010 -> -10

5). code(代码中也有一些解释):

#include <cstdio>
int a;
int tft(int n) {//进制转换 
   	int i , j = 0 , a[100001];
   	i = n;
   	while(i) {
        a[j] = i % 2;
        i /= 2;
        j++ ;
   	}
   	if (j-1 < 8) {//∵位运算是8位二进制补码 
   		for (int k=1; k<=8-(j-1)-1; k++ ) {
   			printf("0");//前面填零方便观看 
		}
	}
   	for(i=j-1; i>=0; i--){
		printf("%d",a[i]);//输出转换后的
    }
    printf(" -> %d",n);
}
int main(void) {
    scanf("%d",&a);
	tft(a);//a数转换后的输出 
	printf("\n");
	printf("%d",~a);
	printf("(这里的%d指~%d算出的值)\n",~a,a);
}
/*
test1.in : 9
test1.out:
00001001 -> 9
-10(这里的-10指~9算出的值)

test2.in : 15
test2.out:
00001111 -> 15
-16(这里的-16指~15算出的值)
*/

取反“~”运算End.


五.左移“<<”运算

1). 表达式:a<<b

2). 表达式意思:整数a的二进制数左移b位

3). 定义:将整数a的各位二进制数左移b位所得到的二进制数再转换成整数。

4). 例子e.g.:66<<2结果为8,because 66对应的二进制是01000010,对01000010进行左移2位得00001000,00001000整数为8

5). code(代码中也有一些解释):

/* 
00000001    1
->结果 如果向左移2位 
00000100    4
*/
#include <cstdio>
int a , b;
int tft(int n) {//进制转换 
   	int i , j = 0 , a[100001];
   	i = n;
   	while(i) {
        a[j] = i % 2;
        i /= 2;
        j++ ;
   	}
   	for(i=j-1; i>=0; i--){
		printf("%d",a[i]);//输出转换后的
    }
    printf(" -> %d",n);
}
int main(void) {
    scanf("%d %d",&a,&b);//a是整数a,b是左移b位 
	tft(a);//a数转换后的输出 
	printf("\n");
	tft((a<<b)&255);//b数转换后的输出,这里是8位整数所以不能用int 
	printf("\n");
	printf("(这里的%d指8位%d<<%d算出的值)\n",(a<<b)&255,a,b);
}
/*
test1.in : 143 2
test1.out:
10001111 -> 143
111100 -> 60
(这里的60指8位143<<2算出的值)
*/

6).注意:

1.最后输出我没有保留8位,手补:00111100 -> 60。

2.这里是8位,而int是32位,所以有(a<<b)&255

3.别把cout<<和a<<b搞混了······

感谢@SIGSEGV和@Veritas指点/kel

左移“<<”运算End.


六.右移“>>”运算

1). 表达式:a>>b

2). 表达式意思:整数a的二进制数右移b位

3). 定义:将整数a的各位二进制数右移b位所得到的二进制数再转换成整数。

4). 例子e.g.:66>>2结果为16,because 66对应的二进制是01000010,对01000010进行右移2位得00010000,00010000整数为16

5). code(代码中也有一些解释):

/* 
00011000    24
->结果 如果向右移2位 
00000110    6
*/
#include <cstdio>
int a , b;
int tft(int n) {//进制转换 
   	int i , j = 0 , a[100001];
   	i = n;
   	while(i) {
        a[j] = i % 2;
        i /= 2;
        j++ ;
   	}
   	for(i=j-1; i>=0; i--){
		printf("%d",a[i]);//输出转换后的
    }
    printf(" -> %d",n);
}
int main(void) {
    scanf("%d %d",&a,&b);//a是整数a,b是右移b位 
	tft(a);//a数转换后的输出 
	printf("\n");
	tft((a>>b)&255);//b数转换后的输出,这里是8位整数所以不能用int 
	printf("\n");
	printf("(这里的%d指8位%d>>%d算出的值)\n",(a>>b)&255,a,b);
}
/*
test1.in : 143 2
test1.out:
10001111 -> 143
100011 -> 35
(这里的35指8位143>>2算出的值)
*/

6).注意:

1.最后输出我没有保留8位,手补:00100011 -> 35。

2.这里是8位,而int是32位,所以有(a>>b)&255,和左移一样

3.别把cin>>和a>>b搞混了······

右移“>>”运算End.


七.拓展延伸

1).运用异或“^”来交换两个数

#include <bits/stdc++.h>
using namespace std;

int x , y;

/*
int tft(int n) {
   	int i , j = 0 , a[10001];
	i = n;
   	while(i) {
    	a[j] = i % 2;
    	i /= 2;
    	j++ ;
   	}
	for(i=j-1; i>=0; i-- ) {
		printf("%d",a[i]);
	}
}
*/

int main(void ) {
	scanf("%d %d",&x,&y);//tft(x);printf(" ");tft(y);printf("\n");
	x ^= y;//tft(x);printf(" ");tft(y);printf("\n");
	y ^= x;//tft(x);printf(" ");tft(y);printf("\n");
	x ^= y;//tft(x);printf(" ");tft(y);printf("\n");
	printf("%d %d",x,y);
} 
话说swap它不香吗?吃饱了撑?(大雾蓝色预警

2).求平均值

#include <bits/stdc++.h>
using namespace std;

int x , y , tmp , tmp1 , tmp2 , tmpsum;

/*
int tft(int n) {
   	int i , j = 0 , a[10001];
	i = n;
   	while(i) {
    	a[j] = i % 2;
    	i /= 2;
    	j++ ;
   	}
	for(i=j-1; i>=0; i-- ) {
		printf("%d",a[i]);
	}
}
*/

int main(void ) {
	scanf("%d %d",&x,&y);//tft(x);printf(" ");tft(y);printf("\n");
	tmp = x & y;//tft(tmp);printf(" ");tft(tmp);printf("\n");
	tmp1 = x ^ y;//tft(tmp1);printf(" ");tft(tmp1);printf("\n");
	tmp2 = tmp1 >> 1;//tft(tmp2);printf(" ");tft(tmp2);printf("\n");
	tmpsum = tmp + tmp2;//tft(tmpsum);printf(" ");tft(tmpsum);printf("\n");
	//总式:tmpsum = (x & y) + ((x ^ y) >> 1);
	printf("%d",tmpsum);
}
不会for?不会数组?(大雾黄色预警

3).整数幂

判断整数n是不是2的整数幂。

例如12 != 2 ^ i 所以输出no

再例如1024=2^10所以输出yes

#include <cstdio>
int n;
int main(void ) {
	scanf("%d",&n);
	if(n & (n - 1)) printf("no");
	else printf("yes");
}
大家看到整数幂第一反应应该都不是这个而是下面这个吧
#include <cstdio>
int n;
int main(void ) {
	scanf("%d",&n);
	while (n && !(n % 2)) {
		n /= 2;
	}
	if (n != 1) printf("no");
	else printf("yes");
}
(大雾橙色预警

4).找数

输入n个数,n为奇数,其中只有一个数出现了奇数次,其余的数都出现了偶数次。问这个出现了奇数次的数。

#include <cstdio>
int n , a , b;
int main(void ) {
	scanf("%d",&n);
	scanf("%d",&a);
	for (int i=2; i<=n; i++ ) {
		scanf("%d",&b);
		a ^= b;
	}
	printf("%d",a);
}

test.in:

5

1 1 2 2 3

test.out:
3

不是。。。你说用桶多好的。。。(大雾红色预警

您也可以在luogu找到这篇文章

posted @ 2021-09-27 00:00  铭矾  阅读(151)  评论(0)    收藏  举报