1.十进制转化为二进制(编译器为32进制)

#include<iostream>
using namespace std;
int main()
{
	int m,number ,s[32];
	cin>>number;
	for(int i=1;i<=32;i++)
		s[i-1]=number>>(i-1)&1;
	for(int i=31;i>=0;i--)
		cout<<s[i]<<' ';
	return 0;
}

2.输入二进制以十进制显示

#include<iostream>
using namespace std;

int show10(char *c)
{
	int num=0;
	for(int i=0;i<=31;i++)
		num=(num<<1)+c[i];
	return num;
}

int main()
{
	int x;
	char c[32];//以字符形式输入32位的二进制
	for(int i=0;i<=31;i++)
		cin>>c[i];
	for(int i=0;i<=31;i++)//字符转换为数字
		c[i]=c[i]-'0';
	cout<<show10(c)<<endl;
	return 0;
}

按位与运算符(&):参数运算的两个运算量,如果两个相应的为都为1,则该位的结果值为1,否则为0.即
0&0=0;0&1=0;1&0=0;1&1=1;
按位运算通常用于二进制取位操作,例如一个数and1的结果就是取二进制的最末位。这可以用来判断一个正整数的奇偶,二进制的最末为0,表示该数为偶数,最末尾为1表示该数为奇数。

//判断奇偶性
#include<iostream>
using namespace std;
int main()
{
	int x;
	cin>>x;
	if((x&1)==0)//注意位运算的优先级很低,所以必须加括号
		cout<<x<<"是欧树"<<endl;
	else
		cout<<x<<"是奇数"<<endl;
	return 0;
}

如果A,B为整数,实际上可看成长度为32的二进制数各个位做上述操作。例如当A=10(二进制为1010),B=12(二进制为1100),A&B=8 (1010&1100=1000)

#include<iostream>
using namespace std;
int main()
{
	int a=10;
	int b=12;
	int c=a&b;
	cout<<c<<endl;//输出结果
	return 0;
}

按位或运算符(|): 两个相应位置中只要有一个为1,该位的结果值就为1.即:0|0=0;0|1=1;1|1=1;
按位运算通常用于二进制特定位上的无条件赋值,例如一个数or1的结果就是把二进制最末尾强行变成1.如果需要把二进制最末尾变成0,
对这个数or1之后再减1就可以了,其实际意义就是把这个数强行变成最接近的偶数。

#include<iostream>
using namespace std;
int main()
{
	int x;
	cin>>x;
	if(x&1==1)
		x=(x|1)-1;//注意按位运算的优先级很低,所以必须加括号
	cout<<x<<"是最接近原数的偶数"<<endl;
	return 0}

如果A,B为整数,实际上可以看成长度32的二进制数各个位做上述操作。例如当A=10(二进制为1010),B=12(二进制为1100)时,A|B=14(1010|1100=1110).

//两个二进制按位或
#include<iostream>
using namespace std;
int main()
{
	int a=10;
	int b=12;
	int c=a|b;
	cout<<c<<endl;//输出结果为14
	return 0;
}

异或运算符(^):它的规则是参加运算的两个相应位同号,则结果为0,异号则结果1,x or r的直观意思就是“是不是不一样“。即:
0^0=0; 0 ^ 0= 1; 1 ^ 0=1; 1 ^ 1= 0;

//两个整数异或
#include<iostream>
using namespace std;
int main()
{
	int a=10;
	int b=12;
	int c=a^b;
	cout<<c<<endl;//输出结果为6
	return 0;
}

x or 运算的逆运算是他本身,也就是说两次异或同一个数最后结果不变,即(a xor b)xor b= a.

//异或加密
#include<iostream>
using namespace std;
int main()
{
	int x=1314520;
	x=x^123475678;
	cout<<"加密后的值为:"<<x<<endl;
	x=x^12345678;
	cout<<"解密后的值为:"<<x<<endl;
	return 0;
}

异或的另一个作用就是交换两个整数,不用临时变量,但是这种方法经检查有一定的局限性,例如不能写在函数里,否则结果会出错,例如快速排序里的swap函数如这样写:
a=a^b;
b=a^b;
a=a^b;
会出现a和b代表相同的元素交换出0的情况。
所以平时让两束交换值得情况还是采用原始的方法较好。(并且该操作并没有明显的时间优势)

#include<iostream>
using namespace std;
int main()
{	
	int a=123;
	int b=789;
	a=a^b;
	b=a^b
	a=a^b;
	cout<<a<<b<<endl;//输出结果为789 123
	return 0;
}

有一组连续的数字,从1到n排列,中间丢失了一个数字,顺序也被打乱,放在一个n-1的数组里,请使用位运算的方法找出丢失的数字
分析:由于1 ^ 1= 0; 2 ^ 2=0; n ^ n=0;因此将n-1个数异或后再来异或一下1,2,……,n。那么最终答案就肯定是迷失的数字k^(1 ^ 1) ^ (2 ^ 2) ^ (3 ^ 3) …… ^ (n ^ n)。其时间复杂度为线性。

//缺失的数字
#include<iostream>
using namespace std;
int find(int a[],int size)
{
	int number = 0;
	for(int i=0;i<size;i++)
		number=number^(i+1)^a[i];//a[10]数组与1~10异或
	number^=(size+1);//与11相异或就可以得到
	return number;
}
int main()
{
	int a[10]={1,2,4,5,6,7,8,9,10,11};
	cout<<find(a,10)<<endl;
	return 0;
}

扩展思考:如果有两个数迷失了呢?
用1 ^ 2 ^ 3 ^ …… ^ n的结果诸葛异或当前输入数据,得到x ^ y。由于x与y不相同,所以x ^ y的结果中至少有一位是1.我们根据这一位的不同(0或1)将输入数据以及1,2,3,……,n。分成两堆进行异或即可得到x和y。(理解不了
与此类似的,N个数,N大到只有保证程序,读入不超时,其中就仅有一个数出现了奇数次,找出这个数的方法是读一个数异或一个,出现偶数个的垦丁抵消了,剩下来的就是那个数了。

//缺失两个数字
#include<iostream>
using namespace std;
int j=1;
int find(int a[],int start,int length)
{
	int number=0;
	for(int i=start;i<=start+length;i++)
	{
		number=number^(i+j)^a[i];
	}
	number^=(Length+j+1+start);
	j++;
	return number;
}
int main()
{	
	int a[10]={1,2,4,5,6,7,9,10,11,12};
	cout<<find(a,0,4)<<endl;//此处不能用cout<<find(a,0,4)<<find(a,5,0)<<endl;会出错
	cout<<find(a,5,4)<<endl;
	return 0;
}

取反运算符(~),用来对一个二进制数按位取反,即将0变1,1变0.例如对二进制数1取反即: ~ 1=0;
例如一个整数a为10,则~a=-11,这里符号也是取反的因此变为负数。

使用取反运算符的时候要格外小心,需要注意整数类型有没有符号。有符号的整数与无符号的整数取反结果是不一样的
。对于有符号类型,取反后效果就是把这个数在数轴上的位置“对折翻着到另一边去“,因为无符号类型的数是用
0X000000000到0xFFFFFFFFFFF依次表示的。
而对于有符号的类型,取反后最高位的变化导致了正负颠倒,又因为负数存储使用补码,所以效果就变为了-a-1.这与上界没有任何关系。

#include<iostream>
using namespace std;
int main()
{
	unsigned short a=100;
	a=~a;
	cout<<a<<endl;
	return 0;
}

左移运算符(<<):A<<B,表示A的所有二进制为整体向左移动B位,后面B位用0补充,与此相对应的为右移符号(>>)。
通常认为a<<1比a*2更快,因为前者是更底层一些操作。因此程序中乘以2的操作尽量用左移一位来代替。

标记:1.最大公约数的二进制算法用除以2的操作来代替慢的出奇的mod运算,效率可以提高60%。
2.数独游戏 需要统计每一行,每一列和每一个小的九宫格里面已经有了那些数了,此时我们可以用27个小于29的整数进行记录。例如,一个只填了2和5的小九宫格就用数字18表示(二进制为000010010),而某一行的状态为511(即二进制111111111)则表示这一行已经填满了。需要改变状态时我们不需要把这个数转成二进制修改后再转回去,而是直接进行位操作。在搜索时,把状态表示成整数可以更好地进行判重等操作。这是在搜索中使用位运算加速的经典例子。

表列举了一些常见的二进制的变换操作。

功能 示例 位运算
去掉最后一位 101101->10110 x>>1
在最后加一个0 101101->1011010 x<<1
在最后加一个1 101101->1011011 (x<<1)+1
把最后一位变成1 101100->101101 x \ 1
把最后一位变成0 101101->101100 (x\1)-1
最后一位取反 101101->101100 x^1
把右数第k位变成1 101001->101101,k=3 x(1<<(k-1))
把右数第k位变成0
右数第k位取反 101001->101101,k=3 x^(1<<(k-1))
取末三位 1101101->101 x&7
//最朴素程序
#include<iostream>
using namespace std;
int main()
{
	int i,x,c=0;
	cin>>x;
	for(i=1;i<=32;i++)
	{
		c=c+(x&1);//判断最末尾是0还是1
		x=x>>1;//去掉最右一位
	}
	cout<<(c&1);//判断奇偶性,是奇数输出1偶数输出0.
	return 0;
}
//位运算
#include<iostream>
using namespace std;
int main()
{
	int x;
	cin>>x;
	x=x^(x>>1);
	x=x^(x>>2);
	x=x^(x>>4);
	x=x^(x>>16);
	cout<<(x&1)<<endl;
	return 0;
}

上式可以表述为如下结果。

#include<iostream>
using namespace std;
int main()
{
	int x;
	int k=1;
	int temp;
	cin>>x;
	for(int i=0;i<5;i++)
	{
		temp=t>>K;
		x^=temp;
		K*=2;	
	}
	cout<<(x&1)<<endl;
	return 0;
}

得到一个新的二进制结果数,其中右起第i位置上的表示原数中第i和i+1位上有奇数个1还是偶数个1.比如,最右边那个0表示原数末两位有偶数个1,右起第三个位上的1就表示原数的第三个和第四个位上有奇数个1.

//用位运算来取一个整数的绝对值
#include<iostream>
using namespace std;
int Abs(int x)
{
	int y;
	y=x>>31;
	return (x^y)-y;
}
int main() 
{
	int x;
	cin>>x;
	cout<<Abs(x);
	return 0;
}

利用二进制运算直接将十进制转化为相应的二进制。

#include<iostream>
using namespace std;
int main()
{
	int number,i,j,m,ok=0;
	int s[50];
	memset(s,0,sizeof(s));//将数组所有元素初始化为0
	cin>>number;
	for(i=1;i<=32;i++)//32位的编译器
	{
		m=number>>(i-1)&1;//将每一位移到最右端与1进行运算
		s[i]=m;
	}
	for(i=49;i>=1;i--)//倒序输出
	{
		if(ok==0&&s[i]==1)//忽略前面的0
			ok=1;
		if(ok==1)
			cout<<s[i];
	}
	return 0;
}

将十进制数转化为相应的十六进制数。

十进制转化为十六进制
#include<iostream>
#include<string>
using namespace std;
int main()
{
	int number,m,i;
	string s;
	cin>>number;
	for(i=0;i<7;i++)
	{
		m=number>>(i*4)&15;//先移动四位再与15(去后四位)
		if(m<10)
			x=char(m+48)+s;//处理数字,注意相加的前后顺序
		else 
			s=char(55+m)+s;//处理字母
	}
	while(s[0]=='0')
		s.erase(0,1);//删除前导0
	cout<<s;
	return 0;
}

//标记

//程序名称:十进制数转化为N进制数
//程序名称:采用除N取余方式,注意特殊数据0的处理
#include<iostream>
using namespace std;
string fun(int x,int n)
{
	const string a="0123456789ABCDEF";
	string s="";
	if(x==0)
		return "0";
	while(x>0)
	{
		s=a[x%n]+s;
		x=x/n;
	}
	return s;
}
int main()
{
	int x,n;
	cin>>x>>n;
	cout<<fun(x,n)<<endl;
	return 0;
}

十进制小数转化为N进制数。转换的方法是“乘N顺序取整“
输入样例:x,n=1065.8125 8
输出样例:2051.64

#include<iostream>
using namespace std;
double x;
int n;
string s;
void fun(double x,int n,int m)
{
	const string a="0123456789ABCDEF";
	int u;
	s='.';
	while(x>0&&m>0)
	{
		m--;//可用小数位数减1
		x=x*n;
		
		s=s+a[int(x)];//去余数依次放后面
		x=x-int(x);//取X的小数部分
	}
}
int main()
{
	cin>>x>>n;
	if(x<1)
		fun(x,n,20);
	cout<<s;
	return 0;
}

N进制转化为十进制

/*
程序名:N进制转为十进制
*/
#include<iostream>
using namespace std;
int fun(int n,string s)
{
	int i,t=0;
	for(i=0;i<s.size();i++)
	{
		if(s[i]>='0'&&s[i]<='9')
			t=t*n+s[i]-48;
		else if(s[i]>='A'&&s[i]<='F')//十六进制
			t=t*n+s[i]-55;
		else if(s[i]>'a'&&s[i]<='f')
			t=t*n+s[i]-87;
	}
	return t;
}
int main()
{
	int n;
	string str;
	cin>>n;
	cin>>str;
	cout<<fun(n,str);
	return 0;
}

N进制小数转换为十进制。转换的基本算法还是“乘权求和“,只是程序有所不同,例如十进制数0.26345如果用2/10+6/100+3/1000+4/10000+5/100000计算的话,计算次数过多,而如果用秦九昭算数计算的话只要左五次除法即可。

//N进制小数转化为十进制
#include<iostream>
using namespace std;
double x,t,j;
double fun(double n,string s)
{
	int i;	
	for(i=s.size();i>=1;i--)
	{	
		if(s[i]>='0'&&s[i]<='9')
			t=t/n+s[i]-48;
		else if(s[i]>='A'&&s[i]<='F')
			t=t/n+s[i]-55;
		else if(s[i]>='a'&&s[i]<='f')
			t=t/n+s[i]-97;
			j=t/n;		
	}
	return j;
}
int main()
{
	int n;
	string s;
	cin>>n;
	cin>>s;
	cout<<fun(n,s);
	return 0;
}

题目描述
N进制加法,N进制数加法运算问题,即从键盘输入一个小于37的正整数N,再输入复合要求的两个N进制数,求两者之和,数出结果仍为N进制数。

//进制数加法
#include<iostream>
using namespace std;
int main()
{
	string a,b,w;
	int x[100],y[100];
	int i,k,N;
	cin>>N;
	for(i=0;i<=n-1;i++)
	{
		if(i<10)
			w=w+char(i+48);//数字的处理
		else 
			w=w+char(55+i);//字母处理
	}
	cin>>a>>b;
	while(a.length()<b.length())
		a='0'+a;
	while(b.length()<a.length())
		b='0'+b;
	a='0'+a;//前面多加一位,用于进位
	b='0'+b;
	for(i=a.length()-1;i>=0;i--)
	{
		x[i]=w.find(a[i],0);//查找a[i]在W中的位置获得真实的数字
		y[i]=w.find(b[i],0);//转换到x,y数组中准备相加
	}
	for(i=a.length()-1;i>=0;i--)//进位加法
	{
		x[i]=x[i]=y[i];//jn
		if(x[i]>=N)
		{
			k=i;
			while(x[k]>=N)
			{
				x[k]=x[k]-N;
				x[k-1]++;
				k--;
			}
		}
		for(i=a.lenght()-1;i>=0;i--)
			a[i]=w[x[i]];//转换为N进制数,a即是加法又是总数
		
		while(a[0]=='0')
			a.erase(0,1);//删除前导0
		cout<<a<<endl;
		return 0;	
	}
}

逃跑路线
假设向上走用1表示,向右走用0表示。请编程统计出修罗王从A地到B地有多少种走法,打印出每一种走法:如0010101.

二进制运算
可以看要从A到达B,不管怎么走都必须向右走4段,向上走3段,也就是说在7位的二进制中所有由4个0和3个1构成的二进制的个数,由于符合条件的最小二进制数为0000111(即十进制7),最大二进制数:1110000(即十进制数112)。因此只要将7~112都转化为二进制数,找出7位二进制中由4个0和3个1构成的二进制数即为所示的走法方案。

#include<iostream>
using namespace std;
int i,j,t,a;
int len,r,r0,r1;
string b,jg;
int main()
{
	t=0;
	for(i=7;i<=112;i++)
	{
		a=i,r0=0,r1=0,jg="";
		do
		{
			r=a%2;
			if(r==1)
				r1++,jg='1'+jg;
			else
				r0++,jg='0'+jg;
			a/=2;
		}while(a!=0);
		len=ji.size();
		if(len<7)
			for(j=0;j<7-len;j++)
				jg='0'+jg;
		if(r1==3&&r0+7-len==4)
		{
			t+=1;
			cout<<jg;
			for(j=8;j<=10;j++)
				cout<<' ';
		}
	}
	cout<<"\n";
	cout<<"t="<<t<<"\n";
	getchar();
	getchar();
	return 0;
}

相关文章: