什么是异或_异或运算及异或运算的作⽤异或,是⼀个数学运算符,英⽂为exclusive OR,缩写为xor,应⽤于逻辑运算。
异或的数学符号为“⊕”,计算机符号为“xor”。其运算法则为:
a⊕b = (¬a ∧ b) ∨ (a ∧¬b)
如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。
异或也叫半加运算,其运算法则相当于不带进位的⼆进制加法:
⼆进制下⽤1表⽰真,0表⽰假,则异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位。
异或略称为XOR、EOR、EX-OR
程序中有三种演算⼦:XOR、xor、⊕。
使⽤⽅法如下
z = x ⊕ y
z = x xor y
异或运算的作⽤
参与运算的两个值,如果两个相应bit位相同,则结果为0,否则为1。
即:
0^0 = 0,
1^0 = 1,
const的作用0^1 = 1,
1^1 = 0
按位异或的3个特点:
(1) 0^0=0,0^1=1 0异或任何数=任何数
(2) 1^0=1,1^1=0 1异或任何数-任何数取反
(3) 任何数异或⾃⼰=把⾃⼰置0
按位异或的⼏个常见⽤途:
(1) 使某些特定的位翻转
例如对数10100001的第2位和第3位翻转,则可以将该数与00000110进⾏按位异或运算。
10100001^00000110 = 10100111
(2) 实现两个值的交换,⽽不必使⽤临时变量。
例如交换两个整数a=10100001,b=00000110的值,可通过下列语句实现:
a = a^b; //a=10100111
b = b^a; //b=10100001
a = a^b; //a=00000110
(3) 在汇编语⾔中经常⽤于将变量置零:
xor a,a
(4) 快速判断两个值是否相等
举例1: 判断两个整数a,b是否相等,则可通过下列语句实现:
return ((a ^ b) == 0)
举例2: Linux中最初的ipv6_addr_equal()函数的实现如下:
staTIc inline int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2) {
return (a1-》s6_addr32[0] == a2-》s6_addr32[0] &&
a1-》s6_addr32[1] == a2-》s6_addr32[1] &&
a1-》s6_addr32[2] == a2-》s6_addr32[2] &&
a1-》s6_addr32[3] == a2-》s6_addr32[3]);
}
可以利⽤按位异或实现快速⽐较, 最新的实现已经修改为:
staTIc inline int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2) {
return (((a1-》s6_addr32[0] ^ a2-》s6_addr32[0]) |
(a1-》s6_addr32[1] ^ a2-》s6_addr32[1]) |
(a1-》s6_addr32[2] ^ a2-》s6_addr32[2]) |
(a1-》s6_addr32[3] ^ a2-》s6_addr32[3])) == 0);
}
5 应⽤通式:
对两个表达式执⾏按位异或。
result = expression1 ^ expression2
参数
result
任何变量。
expression1
任何表达式。
expression2
任何表达式。
说明
^ 运算符查看两个表达式的⼆进制表⽰法的值,并执⾏按位异或。该操作的结果如下所⽰:
0101 (expression1)1100 (expression2)----1001 (结果)当且仅当只有⼀个表达式的某位上为 1 时,结果的该位才为 1。否则结果的该位为 0。
只能⽤于整数
下⾯这个程序⽤到了“按位异或”运算符:
class E
{ public staTIc void main(String args[ ])
{
char a1=‘⼗’ , a2=‘点’ , a3=‘进’ , a4=‘攻’ ;
char secret=‘8’ ;
a1=(char) (a1^secret);
a2=(char) (a2^secret);
a3=(char) (a3^secret);
a4=(char) (a4^secret);
System.out.println(“密⽂:”+a1+a2+a3+a4);
a1=(char) (a1^secret);
a2=(char) (a2^secret);
a3=(char) (a3^secret);
a4=(char) (a4^secret);
System.out.println(“原⽂:”+a1+a2+a3+a4);
}
}
就是加密啊解密啊
char类型,也就是字符类型实际上就是整形,就是数字。
计算机⾥⾯所有的信息都是整数,所有的整数都可以表⽰成⼆进制的,实际上计算机只认识⼆进制的。
位运算就是⼆进制整数运算啦。
两个数按位异或意思就是从个位开始,⼀位⼀位的⽐。
如果两个数相应的位上⼀样,结果就是0,不⼀样就是1
所以111^101=010
那加密的过程就是逐个字符跟那个secret字符异或运算。
解密的过程就是密⽂再跟同⼀个字符异或运算
010^101=111
⾄于为什么密⽂再次异或就变原⽂了,这个稍微想下就知道了。。
异或运算:按位异或运算符
⾸先异或表⽰当两个数的⼆进制表⽰,进⾏异或运算时,当前位的两个⼆进制表⽰不同则为1相同则为0.该⽅法被⼴泛推⼴⽤来统计⼀个数的1的位数!
参与运算的两个值,如果两个相应bit位相同,则结果为0,否则为1。
即:
0^0 = 0,
1^0 = 1,
0^1 = 1,
1^1 = 0
按位异或的3个特点:
(1) 0^0=0,0^1=1 0异或任何数=任何数
(2) 1^0=1,1^1=0 1异或任何数-任何数取反
(3) 任何数异或⾃⼰=把⾃⼰置0
按位异或的⼏个常见⽤途:
(1) 使某些特定的位翻转
例如对数10100001的第2位和第3位翻转,则可以将该数与00000110进⾏按位异或运算。
10100001^00000110 = 10100111
(2) 实现两个值的交换,⽽不必使⽤临时变量。
例如交换两个整数a=10100001,b=00000110的值,可通过下列语句实现:
a = a^b; //a=10100111
b = b^a; //b=10100001
a = a^b; //a=00000110
位运算
位运算时把数字⽤⼆进制表⽰之后,对每⼀位上0或者1的运算。理解位运算的第⼀步是理解⼆进制。⼆进制是指数字的每⼀位都是0或者1.⽐如⼗进制的2转化为⼆进制之后就是10。
其实⼆进制的运算并不是很难掌握,因为位运算总共只有5种运算:与、或、异或、左移、右移。如下表:
左移运算:
左移运算符m《《n表⽰吧m左移n位。左移n位的时候,最左边的n位将被丢弃,同时在最右边补上n个0.⽐如:
右移运算:
右移运算符m》》n表⽰把m右移n位。右移n位的时候,最右边的n位将被丢弃。但右移时处理最左边位的情形要稍微复杂⼀点。这⾥要特别注意,如果数字是⼀个⽆符号数值,则⽤0填补最左边的n位。如果数字是⼀个有符号数值,则⽤数字的符号位填补最左边的n位。也就是说如果数字原先是⼀个正数,
则右移之后再最左边补n个0;如果数字原先是负数,则右移之后在最左边补n个1.下⾯是堆两个8位有符号数作右移的例⼦:
关于移位的运算有这样的等价关系:把整数右移⼀位和把整数除以2在数学上是等价的。
计算机内部只识别1、0,⼗进制需变成⼆进制才能使⽤移位运算符《《,》》 。
int j = 8;
p = j 《《 1;
cout《《p《《endl;
在这⾥,8左移⼀位就是8*2的结果16 。
移位运算是最有效的计算乘/除乘法的运算之⼀。
按位与(&)其功能是参与运算的两数各对应的⼆进制位相与。只有对应的两个⼆进制位均为1时,结果位才为1,否则为0 。参与运算的数以补码⽅式出现。
先举⼀个例⼦如下:
题⽬:请实现⼀个函数,输⼊⼀个正数,输出该数⼆进制表⽰中1的个数。
这⾥⽤到了这样⼀个知识点:把⼀个整数减去1,再和原整数做与运算,会把该整数最右边⼀个1变成0 。 那么⼀个整数的⼆进制表⽰中有多少个1,就可以进⾏多少次这样的操作。
总结:把⼀个整数减去1之后再和原来的整数做位与运算,得到的结果相当于是把整数的⼆进制表⽰中的最右边⼀个1变成0 。
位运算的应⽤可以运⽤于很多场合:
清零特定位(mask中特定位置0,其它位为1 , s = s & mask)。
取某数中指定位(mask中特定位置,其它位为0, s = s & mask)。
举例:输⼊两个整数m和n,计算需要改变m的⼆进制表⽰中的多少位才能得到n。
解决⽅法:第⼀步,求这两个数的异或;第⼆步,统计异或结果中1的位数。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论