按位与(NOT)
在红皮书里,有一个简单的实例和介绍,如下所示:
按位非操作符由一个破浪线(~)表示,执行按位非的结果就是返回数值的反码。
var num1 = 25; //二进制00000000000000000000000000011001
var num2 = ~num1; //二进制11111111111111111111111111100110
console.log(num2);//-26
看了例子一脸懵,怎么就从25到-26了呢,num2的二进制码转换成十进制也不是-26呀,经过百度我才了解-26到底是怎么来的。
- 第一步,会将25转换成二进制,也就是原码 = 00011001
- 第二步,对原码按位取反,也就是反码 = 11100110
- 第三步,反码首位即为符号位,0位正数,1为负数,将除符号位之外的反码进行二次取反 = 10011001
- 第四步,对反码加1,也就是补码 = 10011010
- 最终步,转换为十进制,首位符号位转换成负号,其余会由最后开始乘上2的0次幂,2的1次幂,依次类推 = -26
注:参与运算的会是64位的值,操作时转换成32位,转换二进制时不够位会补零,操作结束后会转换回64位。
但很神奇的是,正数按位非的结果非常有规律
var num1 = 1;
var num2 = ~num1;
console.log(num2); //-2
num1 = 2;
num2 = ~num1;
console.log(num2); //-3
num1 = 3;
num2 = ~num1;
console.log(num2); //-4
也就是说 ~(x) = -(x+1),不难反推负数按位非的结果是 ~(-x) = (x-1)
var num1 = -3;
var num2 = ~num1;
console.log(num2); //2
num1 = -2;
num2 = ~num1;
console.log(num2); //1
num1 = -1;
num2 = ~num1;
console.log(num2); //0
而当二次按位非时,就会是本身
var num1 = -3;
var num2 = ~~num1;
console.log(num2); //-3
num1 = -2;
num2 = ~~num1;
console.log(num2); //-2
num1 = -1;
num2 = ~~num1;
console.log(num2); //-1
浮点数会将小数部分去掉进行按位非
var num1 = 1.1;
var num2 = ~num1;
console.log(num2); //-2
num1 = 2.2;
num2 = ~num1;
console.log(num2); //-3
num1 = 3.3;
num2 = ~num1;
console.log(num2); //-4