位运算在算法中颇有用,速度能够比四则运算快不少。算法
JS中十进制转二进制: (val).toString(2)
JS中二进制转十进制: parseInt(val, 2)
安全
JS中规定安全整数的范围是-2^53~2^53
,因此大于9007199254740991
的数进制转换会存在精度问题spa
读取的十进制是根据原码来读取,而在内存中,数值都是以二进制补码形式保存的code
十进制-5
的二进制表示为:1000,0101
(原码)
原码除符号位外,所有取反再+1:11111011
(补码,内存存储形式)blog
~-5
的结果:索引
负数原码补码转换规则:
符号位不动,从低位往高位数,遇到第一个1以前,包括第一个1不做任何取反,以后,每位都取反。避免了原码转反码再转补码的繁琐。ip
// 7 00000111 // 原码 00000111 // 补码 // -6 10000110 // 原码 11111010 // 补码 // {原码符号位不变} + {数值位从右边数第一个1及其右边的0保持不变,左边安位取反} // -6 10000110 // 原码 11111001 // 反码 11111010 // 补码 // {原码符号位不变} + {数值位按位取反后+1}
进行按位操做,都是针对补码去操做。内存
十进制转二进制
1 1 2 10 3 11 4 100 5 101 6 110 7 111 8 1000
64 64 / 2 = 32 -> 0 32 / 2 = 16 -> 0 16 / 2 = 8 -> 1000 // 转为二进制为:100000 // 十进制 33 能够当作是 32 + 1 ,而且 33 应该是六位二进制的(由于 33 近似 32,而 32 是 2 的五次方,因此是六位),那么 十进制 33 就是 100001 ,只要是 2 的次方,那么就是 1不然都为 0
二进制转十进制
二进制100001
同理,首位是2^5
(1) ,末位是2^0
(0),相加得出33
(只要是 2 的次方,那么就是 1不然都为 0)it
1
(原码)转二进制: 00000001
11111110
10000001
10000010
-2
00000001 // 原码 11111110 // 按位取反 10000001 // 除符号位取反 10000010 // +1
对任一数值 x 进行按位非操做的结果为 -(x + 1), 例如:2 -> -3
class
JS中的做用是配合indexOf()
:indexOf
找到一个给定元素的第一个索引,若是不存在,则返回-1
, -1
取反操做等于0,其它取反操做不等于0
if (~arr.indexOf(v)) if (arr.includes(v)) if (~str.indexOf(v)) if (str.indexOf(v) !== -1)
规则:其中一位为 1,结果就是 1
8 | 7 00001000 00000111 ---------- 00001111 // 15
任一数值 x 与 0 进行按位或操做,其结果都是 x:
6 | 0 00000110 00000000 --------- 00000110 // 6
任一数值 x 与 -1 进行按位或操做,其结果都为 -1:
6 | -1 00000110 10000001 --------- 10000111
将任一数值 x 与 0 进行按位或操做,其结果都是 x。将任一数值 x 与 -1 进行按位或操做,其结果都为 -1
JS中向下取整Math.floor
, 返回小于或等于一个给定数字的最大整数
num | 0 or Math.floor(num)
Math.floor(45.95); // 45.95 | 0 // 45 Math.floor(45.05); // 45.05 | 0 // 45 Math.floor(4); // 4 | 0 // 4 Math.floor(-45.05); // -45.05 | 0 // -46 Math.floor(-45.95); // -45.95 | 0 // -46
1 | 0 ; // 1 1.1 | 0 ; // 1 'asfdasfda' | 0 ; // 0 0 | 0 ; // 0 (-1) | 0 ; // -1 (-1.5646) | 0 ; // -1 [] | 0 ; // 0 ({}) | 0 ; // 0 "123456" | 0 ; // 123456 1.23E2 | 0; // 123 1.23E12 | 0; // 1639353344 -1.23E2 | 0; // -123 -1.23E12 | 0; // -1639353344
规则:每一位都为 1,结果才为 1
8 & 7 // 0 00001000 00000111 00000000 // 0
将任一数值 x 与 0 执行按位与操做,其结果都为 0。将任一数值 x 与 -1 执行按位与操做,其结果都为 x。
JS中应用:
判断奇偶性
10 & 1 // 0 偶数 11 & 1 // 1 奇数
规则:每一位都不一样,结果才为 1
8 ^ 7 // 15 1000 0111 1111 // 15 8 ^ 8 // 0 1000 1000 0000 // 0
将任一数值 x 与 0 进行异或操做,其结果为 x。将任一数值 x 与 -1 进行异或操做,其结果为-x
不进位加法:
根据按位异或的特性就是不进位加法
: 8 ^ 8 = 0
若是进位了,就是 16
了,因此只须要将两个数进行异或操做,而后进位。那么也就是说两个二进制都是1
的位置,左边应该有一个进位1
JS中应用:
交换二个数值
let a = 3 let b = 4 a ^= b b ^= a a ^= b
将第一个操做数向右移动指定的位数,向右被移出的位被丢弃,正数则在高位补零,负数则补1
9 >> 2 00001001 // 移动二位, 以0填充 00000010 // 2 -9 >> 2 10001001 // 原码 11110111 // 补码 11111101 // 补码右移 10000011 // 原码 // -3
公式:int v = a / (2 ^ b)
JS中的应用:
任何小数 把它>> 0
能够取整
9.99 >> 0 // 9 9 >> 0 // 9 9.19 >> 0 // 9
除法运算:
9 >> 1 // 4 8 >> 1 // 4
二分算法中取中间值:
13 >> 1 // 6 12 >> 1 // 6
两个数不使用四则运算得出和
a + b = (a ^ b) + ((a & b) << 1)