位运算中的异或运算什么意思,异或位运算怎么算
位运算是非常迅速的,因为它直接对内存中的二进制数据进行操作。
按位运算除了,按位与,按位非,按位左移,按位右移,还有按位异或。
按位异或运算定义,
1 ^ 1=0
1 ^ 0=1
0 ^ 1=1
0 ^ 0=0
异或,就是"看看你们到底一样不一样。不一样就为1,一样就为0。"
按位异或运算的规律是
定理一=
定理二a ^ b ^ c=a ^(b ^ c)=(a ^ b)^ c;
定理三^ ^=b,^ a^=b,^ a^
定理四若d=a ^ b ^ c,则缺乏维生素
证明:
在^ ^两边同时异或^ b ^ c,得
=
d ^ b ^ c=a ^ b ^ b ^ c ^ c,由定理三得
d ^ b ^ c=a ^ c ^ c,同样由定理三得
^ ^ c=a
(1) 实现两个值的交换,而不必使用临时变量。
例如交换两个整数a=10100001,b=00000110的值,可通过下列语句实现:
a=a^b;//a=10100111
b=b^a;//b=10100001
a=a^b;//a=00000110
(2) 在汇编语言中经常用于将变量置零:
异或答,答
(3) 使某些特定的位翻转
例如对数10100001的第2位和第3位翻转,则可以将该数与00000110进行按位异或运算。
10100001^00000110=10100111
(4)使用定理三进行编码解码
由^ A^ A=B,我们可以假设一聊天记录是b,密钥是答。现在B^A之后,成了密文了。为了解密,对密文再使用密钥A进行一次异或运算即可。也即是^ A^。
看看今年搜狗校招在线测试的一道编码解码题目。原题(JAVA版本)如下
【java】查看plaincopyprint?
公共类测试{ publicstaticvodieencode(byte[]in,byte[]out,int password){ int len=in。长度;intseed=password^0x3e1e25e6;for(inti=0;我leni){bytea=(byte)((in[i]^seed)3);byteb=(byte)((((((int)in[i])18)^seed)(18-5));a=0x1fb=0xe0out[i]=(字节)(a b);seed=(seed*84723701^seed^out[i]);} } publistaticvoiddecode(byte[]in,byte[]out,int password){ int len=in。长度;intseed=password^0x3e1e25e6;for(inti=0;我lenI){//fillthecodehere } } publicstaticvoidmain(String[]args)throw exception { int password=0x FD B4 d0e 9;byte[]buf1={-5,9,-62,-122,50,122,-86,119,-101,25,-64,-97,-128,95,85,62,99,98,-94,76,12,127,121,-32,-125,-126,15,18,100,104,-32,-111,-122,110,-460 byte长度];解码(缓冲器1,缓冲器2,密码);系统。出去。println(新字符串(buf 2, GBK ));} }公共类测试{
公共静态空编码(byte[] in,byte[] out,int password) {
int len=英寸长度
int seed=密码^0x 3 E1 e 25 e 6;
for(int I=0;我leni) {
字节a=(字节)((在[i] ^种子中)3);
字节b=(byte)((((((int)in[I])18)^种子)(18-5));
a=0x1f
b=0xe0
out[i]=(字节)(a b);
seed=(seed * 84723701 ^ seed ^ out[I]);
公共静态空的解码(byte[] in,byte[] out,int password) {
int len=英寸长度
int seed=密码^0x 3 E1 e 25 e 6;
for(int I=0;我leni) {
//在此填写代码
公共静态void main(String[] args)引发异常{
int password=0x FD B4 d0e 9;
byte[] buf1={ -5,9,-62,-122,50,122,-86,119,-101,25,-64,
-97, -128, 95, 85, 62, 99, 98, -94, 76, 12, 127, 121, -32,
-125, -126, 15, 18, 100, 104, -32, -111, -122, 110, -4, 60, 57,
21, 36, -82, };
字节[]缓冲区2=新字节【buf 1。长度];
解码(缓冲器1,缓冲器2,密码);
System.out.println(新字符串(buf2,“GBK”);
题目要求补充译函数。那么根据编码函数就可以补充译函数。解题要点是位运算中的左移,右移,按位与,按位异或,按位异或定理三。
先来理解编码函数。
【java】查看plaincopyprint?
publistativoideencode(byte[]in,byte[]out,int password){ int len=in。长度;intseed=password^0x3e1e25e6;for(inti=0;我leni){bytea=(byte)((in[i]^seed)3);//说明:在[我]中的高5位给了a的低5位byteb=(byte)((((((int)in[i])18)^seed)(18-5));//说明:在[我]中的低3位给了b的高3位a=0x1f//0x1f=16 15=31=2^5-1=00011111;b=0x E0//0x E0=11100000;out[i]=(字节)(a b);seed=(seed*84723701^seed^out[i]);} } public static void encode(byte[]in,byte[] out,int password) {
int len=英寸长度
int seed=密码^0x 3 E1 e 25 e 6;
for(int I=0;我leni) {
byte a=(byte)((在[i] ^种子中)3);
//描述:In[I]的高5位给a的低5位。
byte b=(byte)((((((int)in[I])18)^种子)(18-5));
//描述:in[I]的低3位给b的高3位。
a=0x1f
//0x1f=16 15=31=2^5-1=00011111;
b=0xe0
//0x E0=11100000;
out[i]=(字节)(a b);
seed=(seed * 84723701 ^ seed ^ out[I]);
然后就可以写解码函数了。
【java】查看plaincopyprint?
publicstaticvoiddecode(byte[]in,byte[]out,int password){ int len=in . length;//out[I]in//encode is in[I]int seed=password0x 3 E1 e 25 e 6 in decode here;for(inti=0;我lenI){ bytea=(byte)(in[I]0x1f);//参考公式,还原输出结果,取in[i] byteb=(byte)(in[i]0xe0)的低5位;//参考公式,还原输出结果,取in[i] A=(byte) ((A 3) seed) 248)的高3位;//参考定理3 b a a=b,参考公式bytea=(byte)((in[i]seed)3)//在公式中,in[I]等价于b,seed等价于a,(a 3)等价于b a,所以((a3) seed)表示in[I . //11111000=2^7 2^6 2^5 2^4 2^3=128 64 32 16 8=248 b=(byte)(((((((int)b)(18-5))^seed)18)7);//同理,反推公式,得到的结果会放入out[i]的低3位,所以0000111,即7。//00000111=2^0 2^1 2^2=1 2 4=7 out[I]=(字节)(a b);seed=(seed*84723701^seed^in[i]);} }//最后输出的答案略雷,答案是“真双核引擎是世界上最快的浏览器内核!"公共静态void解码(byte[] in,byte[] out,int password) {
int len=in.length//此处编码中的out[i]是解码中的in[i]
int seed=密码^0x 3 E1 e 25 e 6;
for(int I=0;我leni) {
byte a=(byte)(in[I]0x1f);
//参考公式,还原输出结果,取in[i]的低5位
byte b=(byte)(in[I]0x E0);
//参考公式,还原输出结果,取in[i]的高3位
a=(字节)(((a 3) ^种子)248);
//参考定理3 b a a=b,参考公式 byte a=(byte) ((in [I] seed) 3)
//公式中,in[i]等价于B,seed等价于A,(a 3)等价于B A,所以((A3) seed)表示in[i]高5。
//位的五位数还需要1111000,也就是248,才能把这五位数放在前五位。
//11111000=2^7 2^6 2^5 2^4 2^3=128 64 32 16 8=248
b=(byte)(((((((int)b)(18-5))^种子)18)7);
//同理,反推公式,得到的结果会放入out[i]的低3位,所以0000111,即7。
//00000111=2^0 2^1 2^2=1 2 4=7
out[i]=(字节)(a b);
seed=(seed * 84723701 ^ seed ^ in[I]);
//最后输出答案略雷,答案是“真双核引擎是世界上最快的浏览器内核!"
这个问题还有一个C版本,和JAVA版本几乎一模一样。
【cpp】查看plaincopyprint?
# include 标准传真。h #包含stdio。h//#包含stdlib。h #包含断言。h #包含字符串。h # defineu int 8 _ tunsigned char # defineu int 32 _ tunsigned int # definesize _ tunsigned int inten code(const void * raw _ in,void*raw_out,uint32_tpassword,size _ tlen){ const uint 8 _ t * in=(const uint 8 _ t *)raw _ in;uint 8 _ t * out=(uint 8 _ t *)raw _ out;uint32_tseed=password^0x3feb3c98u;for(size _ ti=0;我leni){uint8_ta=(in[i]^seed)4;uint 8 _ TB=((((uint 32 _ t)in[i])17)^seed)(17-4);a=15//00001111 b=240;//11110000=2^7 2^6 2^5 2^4=128 64 32 16=240 a=15(a^(b 3);out[I]=a b;seed=(seed*48475829^seed^in[i]);} return 0 } int decode(const void * raw _ in,void*raw_out,uint32_tpassword,size _ tlen){ const uint 8 _ t * in=(const uint 8 _ t *)raw _ in;uint 8 _ t * out=(uint 8 _ t *)raw _ out;uint32_tseed=password^0x3feb3c98u;for(size _ ti=0;我leni){//请在此处补全代码-开始uint 8 _ ta=in[I]uint 8 _ TB=in[I]240;a=((一个4)^seed)240;b=((((uint 32 _ t)b 13)^seed)17)out[i]=a b;seed=(seed*48475829^seed^out[i]);//请在此处补全代码-结束} return 0 int main(){ const uint 8 _ tbuf 1[]={0x1e,0x7b,0x8f,0x63,0x6f,0x69,0x26,0x23,0x64,0xe1,0x09,0x21,0x13,0x2b,0x37,0xdf,0xa4,0x7f,0x45,0xe3,0x6b,0xda,0x6a,0x00,0x93,0x4b,0xd1,0x81,0x92,0x20,0x69const uint 32 _ t password=0x e 53 e 6 EB 6u;constsize _ tlen=sizeof(buf 1);decode(buf1,buf2,password,len);printf(%sn ,buf 2);return0}//输出答案:搜狗搜索是全球首个中文网页收录量达到100亿的搜索引擎!