位运算
js 中的位运算只对整数起作用,因为位操作都有 ToInt32 这一步,从而舍弃小数局部
十六进制与二进制转换规则
十六进制 | 二进制 |
---|---|
0 | 0000 |
1 | 0001 |
2 | 0010 |
3 | 0011 |
4 | 0100 |
5 | 0101 |
6 | 0110 |
7 | 0111 |
8 | 1000 |
9 | 1001 |
A | 1010 |
B | 1011 |
C | 1100 |
D | 1101 |
E | 1110 |
F | 1111 |
数的存储
计算机中数是以二进制补码进行存储的,负数的原码、反码、补码都是一样,正数的补码是原码的反码再加 1,这样能够减法运算能够应用加法器实现,符号位也参加运算 ( 二进制的最高位为符号位 0 为正,1 为负,以 8 位来算,最高位为符号位,其余 7 位示意数值 ), 取反码与符号位无关。
int 类型的数占用 4 字节(32 位)。5 转换成二进制是 101,不满 32 位会在后面填充 0。那么 5 在计算机中示意为:
00000000 00000000 00000000 00000101
原码,反码与补码
原码:一个整数,依照绝对值大小转换成的二进制数;
反码:将二进制数按位取反【1 变 0,0 变 1】;
补码:反码加 1;
正数的二进制
如十进制: -5
原码: 00000000 00000000 00000000 00000101
反码:11111111 11111111 11111111 11111010
补码(反码加一):11111111 11111111 11111111 11111011
所以 -5 的二进制是 11111111 11111111 11111111 11111011,转换为十六进制:0xFFFFFFFB
。
二进制求整
如补码是:11111111 11111111 11111111 11110010
补码: 11111111 11111111 11111111 11110010
反码(补码减一):11111111 11111111 11111111 11110001
按位取反,原码:00000000 00000000 00000000 00001110
原码 00000000 00000000 00000000 00001110
即 14, 而后取反就是 -14。
<<
左移
运算规定 :按二进制模式把所有的数字向左挪动对应的位数,高位移出(舍弃),低位的空位补零。
语法格局 :须要移位的数字 << 移位的次数。
数学意义:如果是 10 进制向左挪动一位相当于乘 10 倍,移两位乘 10 的 2 次方倍,所以在数字没有溢出的前提下,对于负数和正数,二进制左移 n 位就相当于乘以 2 的 n 次方。
/** 3 << 2 **/
3 转化为二进制: 00000011
挪动补位:00001100
转化为十进制:12
3 * 2 ^ 2 = 3 * 4 = 12
为什么没有无符号左移<<<?
因为左位移是填补左边空出的位,符号位不影响它的值。
>>
带符号右移
运算规定: 按二进制模式把所有的数字向右挪动对应的位数,低位移出 (舍弃),高位的空位补符号位,即负数补零,正数补 1。【补的位数全副是符号位】
语法格局 :须要移位的数字 >> 移位的次数
数学意义:右移一位相当于除 2,右移 n 位相当于除以 2 的 n 次方。商若为小数,取整即可。
/** 11 >> 2 **/
11 转化为二进制: 0000 1011
挪动补位:0000 0010
转化为十进制:2
11 / 2^2 = 11 / 4 = 2
正数右移
例如:-100 >> 4【-100 带符号右移 4 位】
-100 原码:00000000 00000000 00000000 01100100
-100 反码:11111111 11111111 11111111 10011011
-100 补码:11111111 11111111 11111111 10011100
右移 4 位,在高位补 1:11111111 11111111 11111111 11111001
补码模式的移位实现后,后果不是移位后的后果,要依据补码写出原码才是最初的后果。
减一:11111111 11111111 11111111 11111000
按位取反:00000000 00000000 00000000 00000111
增加符号位:10000000 00000000 00000000 00000111
后果:-7
>>>
无符号右移
>>>
运算符执行无符号右移位运算,它把无符号的 32 位整数所有数位整体右移。最左侧空位不再用符号位的值来填充,而是用 0 来填充。
// 对于无符号数或负数,无符号右移与有符号右移运算后果雷同。console.log(1000 >> 8); // 3
console.log(1000 >>> 8); // 3
console.log(-1000 >> 8); // -4
console.log(-1000 >>> 8); // 16777212
~
非
运算规定: 操作数被转换为 32 位二进制示意(0 和 1)。超过 32 位的数字将抛弃其最高无效位。
语法格局 :~ 操作数。
数学意义 :任何数 x 的运算后果都是-(x + 1)
。~-5
运算后果为 `4;
/** ~ 5 **/
5 转化为二进制: 00000000 00000000 00000000 00000101
位数取反: 11111111 11111111 11111111 11111010【补码】反码:11111111 11111111 11111111 11111001
原码:00000000 00000000 00000000 00000110
增加符号位:10000000 00000000 00000000 00000110
转化为十进制: -6
const a = 5;
console.log(~a); // -6
&
与
运算规定: 第一个操作数的的第 n 位与第二个操作数的第 n 位比照,如果都是 1,那么第 n 位的后果为 1,否则为 0;同真为真,一假为假
。
5 转换为二进制:00000000 00000000 00000000 00000101
3 转换为二进制:00000000 00000000 00000000 00000011
5 & 3 后果:00000000 00000000 00000000 00000001
5 & 3 后果:00000000 00000000 00000000 00000001,转化为二进制是 1;
|
或
运算规定: 第一个操作数的的第 n 位与第二个操作数的第 n 位比照,只有有一个是 1,那么第 n 位的后果为 1,否则为 0;一真为真,同假为假
5 转换为二进制:00000000 00000000 00000000 00000101
3 转换为二进制:00000000 00000000 00000000 00000011
5 | 3 后果:00000000 00000000 00000000 00000111
5 | 3 后果:00000000 00000000 00000000 00000111,转化为二进制是 7;
^
异或
运算规定: 第一个操作数的的第 n 位与第二个操作数的第 n 位比照,如果相同那么第 n 位后果的为 1,否则为 0;同为假,异为真
5 转换为二进制:00000000 00000000 00000000 00000101
3 转换为二进制:00000000 00000000 00000000 00000011
5 ^ 3 后果:00000000 00000000 00000000 00000110
5 ^ 3 后果:00000000 00000000 00000000 00000110,转化为二进制是 6;
理论利用
- 判断奇偶
a & 1 == 0; // 偶数
a & 1 == 1; // 奇数
- 替换两个数的值
异或运算有如下个性:a ^ b ^ a = b; a ^ b ^ b = a
x ^= y;
y ^= x;
x ^= y;