Bitwise Operators JavaScript

   I. Bitwise Operators   

Bitwise operators handling 32 bits

Any numerical value, the calculation of the operands are converted to 32 bits, the result is converted back to the number of JavaScript

Binary bitwise operators for direct calculation, a total of seven operator:

OR (or): symbol | , if the two bits are 0, the result is 0, 1 otherwise;

And operator (and): & symbols , if the two bits are 1, the result is 1, otherwise 0;

No operation (not): ~ symbol for a binary bit inversion;

Exclusive-OR operation (xor): ^ symbol , if the two bits are not the same, the result is 1, otherwise as 0.

Left shift operation (left shift): symbols << 

A right shift operation (right shift): symbols >> 

Arithmetic right shift with sign bits (zero filled right shift): symbols >>> 

 

   Second, bitwise operators Introduction  

Bitwise operators directly address each bit (bit), it is the underlying operations.

Benefits : fast operation;

Drawback : very intuitive operation, many cases can not be used, otherwise it would be difficult to understand the code and troubleshooting.

Note : Bitwise operators act only on integers, if an operator is not an integer, then it is automatically converted into an integer execution .

Inside the JavaScript, values ​​are stored as 64-bit floating point numbers, but when doing bit operations, is 32-bit signed integer operation is performed, and the integer value returned is a 32-bit signed.

 

   Third, you operator characteristics   

(A) and an arithmetic operation or

Comparison of two-digit-by-operator

OR : two bits as long as there is a 11, 1 is returned, otherwise return 0;

And operation : two bits as long as there is a 0, it returns 0, otherwise it returns 1;

0|3;     //3
0&3;   //0
3|4    //7
3&4   //0

And 0 in the above expression 3, in the form of binary 0 and 3, respectively 00 and 11, the "OR operation" will be 11 (i.e., 3); a "and operation" will be 00 (i.e., 0);

In the above expression 3 and 4, 3 and 4 binary form, respectively 11 and 001, the "OR operation" will be 111 (i.e., 7); a "and operation" will be 0 (i.e., 0);

note:

Bit operation is only valid for integer, decimal encountered, the fractional part will be, leaving only the integer portion;

So 0 will be a decimal and "OR", equivalent to the number of fractional part removed, i.e. rounded digit. (This does not apply to rounding manner than the maximum value of a binary 32-bit integer number 2147483648) of

2.7|0; //2
-3.5|0;  //-3

2147483647.4 | 0;   //2147483647
2147483648.4 | 0;   //-2147483648
2147483649.4 | 0;   //-2147483647   

 

(B) No operation

No operation: each bit turned into the opposite of (ie, 0 to 1, 1 to 0), operation mechanism is not very clear so sometimes difficult to understand.

~ 3  // 4

After 3 'no operation' In this expression, it was -4.

Reason is the bit operation, the internal JavaScript all the operator are converted into 32-bit binary integer and then computes.

3 在JavaScript内部是 0000,0000,0000,0000,0000,0000,0000,0011(共32位),否运算后得到11111111111111111111111111111100 ,由于第一位是  1,所以这个数是负数。JavaScript内部采取补码形式表示负数,即需要将这个数减去1,再取一次反,然后加上符号,才能得到这个负数对应的十进制值。这个数减去1等于  11111111111111111111111111111011 ,再取一次反得到 000000000000000000000000000000100,加上负号就是 -4。

这个过程这样计算未免太过麻烦,也可以简单记忆成,一个数与自身的取反值相加,等于 -1。(3的取反值为-4,-3的取反值是2)

注意:

1、对一个整数连续两次 ‘否运算’,可以得到它自身;

2、所有的位运算只对整数有效。否运算遇到小数时,也会将小数部分舍去,只保留整数部分,所以,对一个小数连续两次否运算,就可以达到取整的效果。

3、使用否运算取整,是所有取整方法中最快的一种。

~ -3 // 2
~~3 // 3
~~2.9 // 2
~~47.11 // 47
~~1.9999 // 1
~~3 // 3

1、字符串类型:对字符串进行否运算,JavaScript引擎会先调用 Number 函数,将字符串转为数值。

下面例子相当于  ~Number('011')

~'011' // -12
~'42 cats' // -1
~'0xcafebabe' // 889275713
~'deadbeef' // -1

下面例子相当于  ~~Number('011')

~~'011'; // 11
~~'42 cats'; // 0
~~'0xcafebabe'; // -889275714
~~'deadbeef'; // 0

2、数值的处理是:超出 32位的整数将会被截去超出的位数,NaN 和 Infinity 转为 0;

3、对于其他类型的参数,否运算也是先用 Number 转为数值,然后再进行处理

~~[] // 0
~~NaN // 0
~~null // 0

 

(三)异或运算

异或运算:在两个二进制位不同时返回 1,相同时返回 0;

0 ^ 3 // 3

在这个表达式中,0 的二进制形式是 00,3的二进制形式是 11,它们每一个二进制位都不同,所以得到 11(即3)

异或运算特殊运用:

连续对两个数 a和b 进行 3 次异或运算(a^b, b^a, a^b),可以互换他们的值。这意味着,使用 异或运算 可以在不引用临时变量的前提下,互换两个变量的值。

 运用异或运算互换两个变量的值。这是互换变量值最快的方法。

var a = 10;
var b = 99;
a ^= b, b ^= a, a ^= b;
a // 99
b // 10

通过引用临时变量,互换两个变量的值。

var a = 10;
var b = 99;
var c;
c=a;a=b;b=c;
console.log(a) // 99
console.log(b) // 10

 异或运算也可以用来取整,与 0 一起运算

12.9 ^ 0 // 12

 

(四)左移运算符

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

// 4 的二进制形式为100,
// 左移一位为1000(即十进制的8)
// 相当于乘以2的1次方
4 << 1
// 8
-4 << 1
// -8

这个例子中, -4左移一位得到 -8,是因为 -4 的二进制形式是 11111111111111111111111111111100 ,左移一位后得到 11111111111111111111111111111000,把这个数字转换为十进制(减去1后取反,再加上符号)结果为 -8;

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

13.5 << 0
// 13
-13.5 << 0
// -13

左移运算用于二进制取值非常方便:

实例:

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


var colo {r: 186, g: 218, b: 85};
// RGB to HEX
// (1 << 24)的作用为保证结果是6位数
var rgb2hex = function(r, g, b) {
  return '#' + ((1 << 24) + (r << 16) + (g << 8) +
.toString(16) .substr(1); }rgb2hex(color.r,color.g,color.b) // "#bada55"

 

(五)右移运算符

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

4 >> 1

 

 在这个例子中,因为 4的二进制形式为 00000000000000000000000000000100,向右移动一位之后(在头部补 0 ),得到 00000000000000000000000000000010,即为十进制的 2。

-4 >> 1

 在这个例子中,-4 的二进制形式为 11111111111111111111111111111100,右移一位,头部补 1(二进制采取补码的形式表示负数),得到 11111111111111111111111111111100,即为十进制的 -2。

使用右移运算符模拟 2 的倍数

5 >> 1
// 相当于 5 / 2 = 2,101转换为10,即为2
21 >> 2
// 相当于 21 / 4 = 5,10101转换为101,即为5
21 >> 3
// 相当于 21 / 8 = 2,10101转换为10,即为2
21 >> 4
// 相当于 21 / 16 = 1,10101转换为1,即为1

 

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

带符号的右移运算符:表示将一个数的二进制形式向右移动,包括符号位也参与移动,头部补 0。

所以,该运算总是得到正数。对于正数,该运算的结果与右移运算符(>>)完全一致,区别只要在于负数。

4>>>1

-4>>>1

在这个例子中,-4 的二进制形式为 11111111111111111111111111111100,带符号位的右移一位,头部补0,得到 0111111111111111111111111111110,即为十进制的 2147483646。

这个运算实际上将一个值转为 32 位无符号整数。

查看一个负整数在计算机内部的储存形式,最快的方法就是使用这个运算符。

-1>>>1

-1 作为 32 位整数时,内部储存形式使用无符号正数格式解读,值为4294967295(即 ( 2^32)-1,等于11111111111111111111111111111111)

 

   四、设置对象属性开关   

位运算符可以用作设置对象属性的开关

加定某个对象有四个开关,每个开关都是一个变量。那么就可以设置一个四位的二进制数,它的每个位都对应一个开关。

var flag_A = 1; // 0001
var flag_B = 2; // 0010
var flag_C = 4; // 0100
var flag_D = 8; // 1000

上面代码设置 A、B、C、D四个开关,每个开关分别占了有一个二进制位。然后,就可以使用 ‘与运算’ 检验,当前设置是否打开了指定开关。

var flags = 5; // 二进制的0101
if (flags & FLAG_C) {
 // ...
}
// 0101 & 0100 => 0100 => true

上面代码检验是否打开了 开关C。如果打开,返回 true,否则返回 false。

现在假设 需要打开ABD三个开关,可以构建一个掩码变量

var mask = FLAG_A | FLAG_B | FLAG_D;
// 0001 | 0010 | 1000 => 1011

上面代码对A B D三个变量进行 ‘或运算’,得到掩码值为二进制的1011。有了掩码,‘或运算’ 可以确保打开指定的开关。

flags = flags | mask;

“与运算” 可以将当前设置中凡是与开关设置不一样的项,全部关闭

flags = flags & mask;

“异或运算” 可以切换(toggle)当前设置,即第一次执行可以得到当前设置的相反值,再执行一次,可以得到原来的值。

flags = flags ^ mask;

“否运算”可以翻转当前设置,即原设置为 0 ,运算后变为 1 ;原设置为 1 ,运算后变为 0;

flags = ~flag

 

 

Guess you like

Origin www.cnblogs.com/nyw1983/p/11880976.html