//分析如下 25 = 0000 0000 0000 0000 0000 0000 0001 1001 3 = 0000 0000 0000 0000 0000 0000 0000 0011 --------------------------------------------- XOR = 0000 0000 0000 0000 0000 0000 0001 1010
“异或运算”有一个特殊运用,连续对两个数a和b进行三次异或运算,aˆ=b, bˆ=a, aˆ=b,可以互换它们的值。这意味着,使用“异或运算”可以在不引入临时变量的前提下,互换两个变量的值
var a=10,b=9; a ^= b, b ^= a, a ^= b; console.log(a,b);//9,10
//分析如下 a = 0000 0000 0000 0000 0000 0000 0000 1010 b = 0000 0000 0000 0000 0000 0000 0000 1001 --------------------------------------------- a1 = 0000 0000 0000 0000 0000 0000 0000 0011 a1 = 0000 0000 0000 0000 0000 0000 0000 0011 b = 0000 0000 0000 0000 0000 0000 0000 1001 --------------------------------------------- b1 = 0000 0000 0000 0000 0000 0000 0000 1010 b1 = 0000 0000 0000 0000 0000 0000 0000 1010 a1 = 0000 0000 0000 0000 0000 0000 0000 0011 --------------------------------------------- a2 = 0000 0000 0000 0000 0000 0000 0000 1001 //a=a2=10;b=b1=9
一个整数与0按位异或可以保持其自身,一个小数与0按位异或可以取整
console.log(3.1 ^ 0);//3 console.log(3.9 ^ 0);//3
左移
左移操作符由两个小于号(<<)表示,这个操作符会将数值的所有位向左移动指定的位数
例如,如果将数值2(二进制码为10)向左移动5位,结果就是64(1000000)
var oldValue = 2; var newValue = oldValue<<5; console.log(newValue);//64
左移不会影响操作数的符号位。换句话说,如果将-2向左移动5位,结果将是-64
var oldValue = -2; var newValue = oldValue<<5; console.log(newValue);//-64
左移0位可以实现取整效果
console.log(3.1 << 0);//3 console.log(3.9 << 0);//3
有符号右移
有符号的右移操作符由两个大于号(>>)表示,这个操作符会将数值向右移动,但保留符号位(即正负号标记)。有符号的右移操作与左移操作正好相反,即如果将64向右移动5位,结果将变回2
var oldValue = 64; var newValue = oldValue>>5; console.log(newValue);//2
同样,在移位过程中,原数值中也会出现空位。只不过这次的空位出现在原数值的左侧、符号位的右侧。而此时ECMAScript会用符号位的值来填充所有空位,以便得到一个完整的值
右移可以模拟2的整除运算
console.log(5>>1);//2 console.log(15>>1);//7
无符号右移
无符号右移操作符由3个大于号(>>>)表示,这个操作符会将数值的所有32位都向右移动。对正数来说,无符号右移的结果与有符号右移相同。仍以前面有符号右移为便,如果将64无符号右移5位,结果仍然是2
var oldValue = 64; var newValue = oldValue>>>5; console.log(newValue);//2
但是,对负数就不一样了。首先,无符号右移是以0来填充空位,而不是像有符号右移那样以符号位的值来填充空位。所以,对正数的无符号右移与有称号右移结果相同,但对负数的结果就不同了。其次,无符号右移操作符会把负数的二进制码当成正数的二进制码。而且,由于负数以其绝对值的二进制补码形式表示,因此就会导致无符号右移后的结果非常之大
var oldValue = -64; var newValue = oldValue>>>5; console.log(newValue)//134217726
要确定-64的二进制表示,首先必须得到64的二进制表示,如下所示:
0000 0000 0000 0000 0000 0000 0100 0000
接下来,计算二进制反码,如下所示:
1111 1111 1111 1111 1111 1111 1011 1111
最后,在二进制反码上加 1,如下所示
1111 1111 1111 1111 1111 1111 1011 1111 1 --------------------------------------- 1111 1111 1111 1111 1111 1111 1100 0000
向右移动5位后,如下所示:
0000 0111 1111 1111 1111 1111 1111 1110 console.log(0b00000111111111111111111111111110);//134217726
常见应用
【1】乘法运算
利用左移(<<)来实现乘法运算
console.log(2 << 1);//4 console.log(3 << 1);//6 console.log(4 << 1);//8
【2】除法运算
利用有符号右移(>>)来模拟2的整除运算
console.log(2 >> 1);//1 console.log(5 >> 1);//2 console.log(8 >> 1);//4 console.log(9 >> 1);//4
【3】值互换
利用异或操作(^)可以实现值互换的效果
var a=10,b=9; a ^= b, b ^= a, a ^= b; console.log(a,b);//9,10
【4】小数取整
利用取两次按位非、与0按位或、与0按位异或、左移0位、右移0位都可以实现小数取整效果
console.log(~~3.1);//3 console.log(3.1|0);//3 console.log(3.1^0);//3 console.log(3.1<<0);//3 console.log(3.1>>0);//3
【5】开关