js位运算符

位运算符整理

原文地址:http://javascript.ruanyifeng.com/grammar/operator.html#toc16

一 简介

位运算符用于直接对二进制位进行计算,有7个。

这些运算符能直接处理每一个比特位(bit),所以是非常底层的运算。好处是速度快,缺点是不直观。

二 位运算符使用

“或运算”与“与运算”

或运算(|):两个二进制位中只要有一个为1,就返回1,否则返回0
与运算(&):两个二进制位中都为1,才返回1,否则返回0

console.log(0 | 3); //3
console.log(0 & 3); //0

上面两个表达式,0和3的二进制形式分别是 0011

位运算符只对整数起作用。如果一个运算子不是整数,会自动转为整数后再执行。另外,虽然在JS内部,数值都是以64位浮点数的形式存储,但做位运算时,是以32位带符号的整数进行运算的,并且返回值也是一个32位带符号的整数。所以下面的代码是将i(不管是整数或小数)转为32位带符号的整数。

i = i | 0;
console.log(2.9 | 0);   //2
console.log(-2.9 | 0);  //-2

但是这种取整方法不适合超过32位整数最大值2147483647的数

console.log(2147483647 | 0);    //-2147483647
console.log(2147483648 | 0);    //-2147483648
console.log(2147483649 | 0);    //-2147483647

否运算

否运算(~)将每个二进制位都变为相反值(0变为1,1变为0)

console.log(~3);    //-4

运算过程:位运算时,JS内部将所有的运算子都转为32位的二进制。3转为00000000000000000000000000000011,否运算得到11111111111111111111111111111100。第一位是1,所以这个数是一个负数。JS内部采用补码形式表示负数,也就是这个数需要减去1,再取一次反,然后加上负号。上面的值减去1得到11111111111111111111111111111011,取反得到00000000000000000000000000000100,十进制数就是4,加负号就是-4。这样的过程比较麻烦,可以简单记忆成,一个数与自身的取反值相加等于-1。

console.log(~-3)    //2
console.log(~~3);   //3

一个整数连续两次“否运算”,得到它自身。

对字符串进行否运算,JS引擎会先调用Number函数,将字符串转为数值,然后再进行处理。

console.log(~'011');    //-12
console.log(~'42 fdsa');    //-1
console.log(~'0xcafebabe'); //889275713

console.log(~~'011');    //11
console.log(~~'42 fdsa');    //0
console.log(~~'0xcafebabe'); //-889275714

Number函数将字符串转换为数值的规则,请参看http://javascript.ruanyifeng.com/grammar/conversion.html#toc1

异或运算

在两个二进制位不同时返回1,相同时返回0。

console.log(3 ^ 1); //2

上面的表达式中,3的二进制形式是11,1的二进制形式是01,二进制位不同时返回1,相同时返回0,得到10,换为十进制为2。

任意一个变量X与自身进行异或运算,结果为0。
任意一个变量与0进行异或运算,结果不变。
异或运算具有结合性,即a ^ b ^ c = (a ^ b) ^ c = a ^ (b ^ c)
异或运算具有交换性,即a ^ b = b ^ c

console.log(3 ^ 0); //3
console.log(3 ^ 3); //0

采用上面的原理,可以通过异或运算交换两个变量而不需借助第三个临时变量。

a = a ^ b;
b = a ^ b;
a = a ^ b;

分析
- 第一步: 完成后a变量的结果为a ^ b
- 第二步: 此时赋值号右边的a保存的是a ^ b 的值,所以赋值号右边等价于(a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a ,所以经过第二步运算后b的值为a
- 第三步: 此时赋值号右边a保存的是 a ^ b 的值,b保存的是 a ,所以赋值号右边的值为 (a ^ b) ^ a = (a ^ a) ^ b = 0 ^ b = b,所以经过第三步的运算后a的值为b。

根据 a = a ^ b 可以简化为 a ^= b,上面的代码可以简化为

a ^= b;
b ^= a;
a ^= b;

这是交换两个变量的值的最快方法。

左移运算(<<)

左移运算符表示将一个数的二进制值向左移动指定的位数,尾数补0,即乘以2的指定次方(最高位符号位不参与移动)。

console.log(4 << 1);    //8
//4的二进制形式为100,左移一位相当于1000,即十进制的8,相当于乘以2的1次方
console.log(-4 << 1);   //-8
//-4的二进制形式是11111111111111111111111111111100(4的二进制形式减1再取反),左移一位得到11111111111111111111111111111000,转换为十进制得到-8(减1后再取反)

如果左移0位,相当于将该数值转换为32位整数,等同于取整,对于正数和负数都有效。

console.log(13.5 << 0); //13
console.log(-13.5 << 0);    //-13

使用左移运算符,将颜色的RGB值转为HEX值。

var rgb2hex = function(r,g,b){
// (1 << 24)的作用是保证结果是6位数。比如r==0的情况
    return '#' + ((1<<24)+(r<<16)+(g<<8)+b).toString(16).substr(1);
}
console.log(rgb2hex(0, 255, 255));  //#00ffff

右移运算符(>>)

表示将一个数的二进制值向右移动指定位数,头部补0,即除以2的指定次方(最高位符号位不参与移动)。

console.log(4 >> 1);    //2
console.log(-4 >> 1);   //-2

可以模拟2的整除运算

console.log(5 >> 1);    //2 相当于5整除2
console.log(21 >> 2);   //5 相当于21整除4

带符号位的右移运算符(>>>)

该运算符表示将一个数的二进制形式向右移动,包括符号位也参与移动,头部补0,所以该运算总是得到正值。对于正数,该运算的结果与右移运算符(>>)完全一致,区别主要在于负数。

console.log(-4 >>> 1);  //2147483646

因为-4的二进制形式为11111111111111111111111111111100 整体右移一位,得到01111111111111111111111111111110 ,转换为十进制得到2147483646。
查看一个负整数在计算机内部的储存形式,最快的方法就是使用这个运算符。

console.log(-1 >>> 0);  //4294967295

上面代码表示,-1作为32位整数时,内部的存储形式使用无符号整数格式解读,值为4294967295(换为二进制为11111111111111111111111111111111

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值