位运算

/*
位运算符是在数字底层(即表示数字的 32 个数位)进行操作的
有符号32位整数
所有的按位操作符的操作数都会被转成[补码]形式的有符号32位整数
32位整数的表示范围:
数字-2147483648 和 2147483647 是32位有符号数字所能表示的最小和最大整数
0 是所有比特数字0组成的整数
0 (base 10) = 00000000000000000000000000000000 (base 2)
-1 是所有比特数字1组成的整数
-1 (base 10) = 11111111111111111111111111111111 (base 2)
-2147483648十六进制形式:-0x80000000
-2147483648 (base 10) = 10000000000000000000000000000000 (base 2)
2147483647十六进制形式:0x7fffffff
2147483647 (base 10) = 01111111111111111111111111111111 (base 2)

[位运算可以模拟点电路设计开关]:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#例子:标志位与掩码

[补码]:取反加1.
补码保证 当一个数是正数时,其最左的比特位是0
当一个数是负数时,其最左的比特位是1
即 最左边的比特位称为符号位
[反码]:按位非
整数314 00000000000000000000000100111010
314反码~314 11111111111111111111111011000101
314补码-314 11111111111111111111111011000110



1、toString(x) : x表示进制 数字转换成二进制字符串
9.toString(2) // 1001


2、负数的二进制表示形式是 二进制补码

但是 ECMAScript 并不以二进制补码的形式显示,‘
而是用数字绝对值的标准二进制代码前面加负号的形式输出
(-9).toString(2) // -1001

3、按位非not: ~ (对数字求负,然后减 1) ~25 = -26
把运算数转换成 32 位数字
把二进制数转换成它的二进制反码
把二进制数转换成浮点数
var iNum1 = 25; //25 等于 00000000000000000000000000011001
var iNum2 = ~iNum1; //转换为 11111111111111111111111111100110
alert(iNum2); //输出 “-26”

4、按位与&: 也相当于串联 1&1 =1 其余(1&0\0&1\0&0都是false)
x&1 表示x的最低二进制位是否为1 即是判断 x是奇数还是偶数
2&1=0
3&1=1
1&0=0

5、按位或|: 并联:两个为false 输出为false
0|0:0
1|0:1

6、异或 ^:两个相异时 为true
1^1=0
1^0=1
0^0=0
异或操作的特点:异或也可以 理解为 不进位加
x^0 = 0
x^1s(全1的数) = ~x
x^(~x) = 1s
x^x = 0 [❗important and interesting]
用异或实现两个数交换
a^b^c = a^(b^c) = (a^b)^c // 异或满足 交换律

7、左移<<(添0 变大):把数字中的所有数位向左移动指定的数量==> 4<<1 // 4*2
2(10) <<5 // 64(1000000) 加了5个0
-2(10)<<5 // -64

8、右移>> (减0 变小): 4>>1 // 2


*/

/**
JS是一种弱类型的脚本语言,
所有的数值无论是整数还是小数,其实都是按照64为位的浮点形式存储

然而当两个整数在进行位运算时,却又会自动转化为32位的有符号整数

JS每次最多只能处理32位的位运算
*/

/*
常见应用:
1、左移实现乘2
2<<1 // 2
3<<1 // 6

2、右移实现整除2 (向下取整)
9>>1 // 4

3、异或实现值互换
var a=10,b=9;
a ^= b, b ^= a, a ^= b;
console.log(a,b);//9,10

4、小数取整
~~3.1、3.1|0、3.1^0、3.1<<0、3.1>>0

5、判断奇偶
// normal
n%2==1 //奇数
// better
x&1 == 1 [奇数] x&1 ==0 [偶数]

[算法题常用]
清零最低位1 [=> 求二进制中1的个数
x = x&(x-1)
如 x= 101000000,
则x-1= 100111111, x&(x-1) = 100000000
得到最低位1 ?
x = x&-x
如 x= 101000000,
则 -x= 011000000, x&(-x) = 11


一个推广:k个相同的k进制数进行无相位相加,
相加的结果一定是每位都是0的k进制数

二进制的简化: x^x = 0;0^x=x



*/

/**
@func 元素除以2取整
/

// normal
mid = ~~((right-left)/2)
mid = (right-left)/2>>0;

// better
mid = (right-left)>>1;

// (left+right)/2
// better:为了防止溢出
mid = left + ((right-left)>>1);

/**

@func m进制的数转换n进制数
parseInt:将字符串str按照x进制编码方式转换为10进制
toString:数字的指定进制形式的字符串

/

num = num.toString(2)// 将数值num转换为2进制显示
num = parseInt(‘23’,8)// 将字符串23按照8进制的编码方式转换为10进制

// 将数值num从m进制转换为n进制
num = (parseInt(String(num),m).toString(n))*1

数学

/**
掌握一定的数学公式 可以简化很多程序步骤

/

/**
@desc 棋盘,平面坐标-判断平面上两点是否在同一斜线上
row1: 0 0 1 0 0
row2: 0 0 0 0 1
row3: 1 0 0 0 0
row4: 0 0 0 1 0
row5: 0 1 0 0 0

row1和row3可以攻击.. 原来对角线定义这么广泛啊555
row2和row5可以攻击

===> 快速有效判断平面上两点是否在同一斜线上
已知两点a、b,他们坐标分别为 a(i,j),b(m,n),如果他们在同一对角线线上则满足:
|i-m| = |j-n| (|| 绝对值)
*/

/*
@desc 解析几何:
应用:平面对、 凸包问题
[解析几何的根本思想是将几何问题简化为几何问题]

p1=(x1,y1) p2=(x2,y2),p3=(x3,y3) 是平面上任意三点
当且仅当p3在穿越p1p2的有向直线的左边时 行列式
|x1,y1,1|
|x2,y2,1| = x1y2+x3y1+x2y3-x3y2-x1y3-x2y1 > 0
|x3,y3,1|
/

精炼代码

/**
@func 条件判断简略
/

// 条件判断
condition1&&condition2();
// 相当于
if(condition1){
condition2()
}

var a = b&&1;
// 相当于
if(b){
a = 1;
}else{
a=b;
}

//————————————————//
condition1||condition2() // 如果条件1不存在 则执行条件2 娄底写法
var a = b||1;
if(b){
a = b
}else{
a=1
}

/**
@func 数组复制
/
let arr = [1,2,3];

let arr1 = arr; // ❌ 修改arr1会改变arr,比如往arr1里push数据

// right:✅
arr2 = arr.slice();
arr3 = arr.concat();
arr4 = […arr];
arr5 = Array.from(arr);

/**
申请长度为n的数组,并且数组所有元素初始化为1


*/
let arr1 = Array.from({length: n}, _ => 1);
let arr2 = new Array(n).fill(1);

踩坑

/**
二维矩阵的生成

以为可以:
let mark = new Array(n+1).fill([]);
实际上fill的那个数组 是 指向一个地址


/

// 死循环看出来了吗
let count = 3;
while(count>0){
if(count==2)continue;
console.log(count)
count -=1;
}

逻辑运算符

/**

1、ToBoolean

2、逻辑非:!

2.5、!! js的!! 即是模拟Boolean()转型函数
!!undefined // false

3、逻辑与:&& 只有都为真才是真 串联 与 位与一致

4、逻辑或:|| 并联 与 位或 一致
常用于为变量设置默认值 p = p||{}
5、

*/