Appearance
二进制
位运算符
| 符号 | 描述 | 运算规则 |
|---|---|---|
| & | 与 | 两个位都为 1 时,结果才为 1 |
| | | 或 | 两个位都为 0 时,结果才为 0 |
| ^ | 异或 | 两个位相同为 0,相异为 1 |
| ~ | 取反 | 0 变 1,1 变 0 |
| << | 左移 | 各二进位全部左移若干位,高位丢弃,低位补 0 |
| >> | 右移 | 各二进位全部右移若干位,低位丢弃,高位补 0 |
&与运算(两个位都为 1 时,结果才为 1 )
js
0&0=0
0&1=0
1&1=1
// 判断奇偶(如果最低位是1,则是偶数,后面都是2的倍数)
12&1=0 // 偶
13&1=1 // 奇|或运算(两个位都为 0 时,结果才为 0)
js
0|0=0
0|1=1
1|1=1
// 或0取整
100.11|0=100
// 或自身等于自身
235|235 = 235^异或运算(两个位相同为 0,相异为 1)
js
0^0=0
1^1=0
1^0=1
// 异或自身等于0(归零律)
100^100=0
// 异或0等于自身(恒等律)
100^0=100
// 结合律
100^0=100
// 与顺序无关
a^b^c==c^b^c
// 数据交换
let a = 10;
let b = 20;
a = a ^ b;
b = b ^ a;
a = a ^ b;
console.log(a);
console.log(b);
[b,a]=[a,b]~取反运算
- 取反在减一
js
~0 == -1;
~1 == -2;
~5 == -6;位移运算
- 1、<< 左移
- 2、>>>无符号右移
- 3、>>有符号位移
"<<"运算符
- 运行原理:"<<"运算符执行
左移位运算。在移位运算过程中,符号位始终保持不变。如果右侧空出位置,则自动填充为 0;超出 32 位的值,则自动丢弃。
js
console.log(5 << 2); //20
">>"运算符
- 运行原理:">>"运算符执行有符号
右移位运算。与左移运算操作相反,它把 32 位数字中的所有有效位整体右移,再使用符号位的值填充空位。移动过程中超出的值将被丢弃。
js
conosle.log(1000 >> 8); //3
js
console.log(-1000 >> 8); //-4
">>>"运算符
- 运行原理:">>>"运算符执行五符号右移位运算。它把无符号的 32 位整数所有数位整体右移,
无符号右移与有符号右移运算的结果是相同的。
js
console.log(1000 >> 8); //返回值3
console.log(1000 >>> 8); //返回值3
console.log(-1000 >> 8); //返回值 -4
console.log(-1000 >>> 8); //返回值 16777212
二进制权限控制
- 假设我们需要设计一个读、写、执行三种权限,每一个可以任意组合,我们可以通过二进制来控制
js
let r = 1 << 0; // 1(读)
let w = 1 << 1; // 2(写)
let x = 1 << 2; // 4(执行)
// 或(|)运用符,一个为1则为1
let add = r | w | x; // 7(所有权限)
// 给张三加读写权限
let zhangsan = r | w;
console.log(zhangsan & r);
console.log(zhangsan & w);
// 取消张三可读权限
// 异或两个位相同为 0
zhangsan = zhangsan ^ r;
console.log(zhangsan & r);0.1+0.2!=0.3
- 1、因为在计算的时候十进制会转成二进制
- 2、小数在转化二进制的时候会乘 2,取出整数部分,有剩余的小数部分继续乘 2
- 3、0.1 / 0.2 转换的时候会进入死循环,尾数超过 52 位会被丢弃,导致计算不正确
js
0.1转化成二进制的算法:
0.1*2=0.2======取出整数部分0
0.2*2=0.4======取出整数部分0
0.4*2=0.8======取出整数部分0
0.8*2=1.6======取出整数部分1
0.6*2=1.2======取出整数部分1
0.2*2=0.4======取出整数部分0
0.4*2=0.8======取出整数部分0
0.8*2=1.6======取出整数部分1
0.6*2=1.2======取出整数部分1
接下来会无限循环
0.2*2=0.4======取出整数部分0
0.4*2=0.8======取出整数部分0
0.8*2=1.6======取出整数部分1
0.6*2=1.2======取出整数部分18 进制转二进制
- 8 进制 0-7,0 作为开头
- 一个八进制,占三位
js
// 八进制对应的二进制表现方式
let a = 016; // 001 110
let b = 0123; // 001 010 01110 进制转二进制
- 整数部分: 除 2 取余,直到商为 0,最先得到的余数是最低位,最后得到的余数是最高位.
- 小数部分: 乘 2 取整,直到积为 0 或者达到精度要求为止,最先得到的整数是高位
- 例如 (7.75)10=(111.11)2
- 高位在左,低位在右

16 进制转二进制
- 16 进制 0-9、字母 A 到 F(或 a~f)->10-15,0x 作为开头
- 一个 16 进制,占四位
js
// 八进制对应的二进制表现方式
let a = 0x1a; // 0001 1010
let b = 0x1f; // 0001 11112 进制转 8 进制
- 三个位代表一个 8 进制
js
let a = 001110; // 001 110 => 016
let b = 001010011; // 001 010 011 => 01232 进制转 10 进制
TIP
- 负次计算: 一个数的负几次方就是这个数的几次方的倒数。
- 2 的负 1 次方= 2 的 1 次方分之一= 1/2
- 3 的负 2 次方= 3 的 2 次方分之一= 1/9
- 4 的负 2 次方= 4 的 2 次方分之一= 1/16
- 方法: 按权展开,加权求和,以(111.11)2 为例

2 进制转 16 进制
- 四个位代表一个 16 进制
js
let a = 00011010; // 0001 1010 => 0x1a
let b = 00011111; // 0001 1111 => 0x1f计算机中的数据
- 一个字节有 8 位(11111111)二进制,一个 bit 等于一位(1)二进制,
数据
- 1、数值数据
- 无符号数据(没有正负符号为)
- 有符号数据(有正负符号为)0 为正,1 为负
- 2、数值数据
- 文字
- 图像
无符号数据的表示(原码)
- 原码: 3 个 bit(111)能表示 8 个数
0、1、2、3、4、5、6、7
有符号数据的表示(原码)
- 原码: 3 个 bit 能表示 8 个数
+0、+1、+2、+3、-0、-1、-2、-3 - 符号: 用
0、1表示正、负号,放在数值的最高位
有符号数据(反码)
- 反码:
正数不变,负数的除符号位外取反
有符号数据(补码)
- 补码:
正数不变,负数在反码的基础上加 1
原码、反码、补码
TIP
- 计算机里的数都是
补码的形式
正数的补码、反码和原码一样
- 例如:7
- 原码:0111
- 反码:0111
- 补码:0111
负数:通过
原码求补码的转换方法:符号位不变,每个数值位求反(反码),末位加 1- 例如:-7
- 转为二进制原码:1111
- 从原码转为反码:1000
- 从反码转为补码:1001
c
#include <stdio.h>
int main() {
unsigned char ch;
// 计算机都是以补码的形式计算
// 00000001 // 原码
// 11111110 // 反码(原码取反)
// 11111111 // 补码(反码+1)
ch = -1;
printf("ch=%d %c\n", ch, ch); // 255 %c ASCII 没有对应的255所以是乱码
return 0;
}IEEE754 标准
- JavaScript 采用的是双精度(64 位)
符号位决定了一个数的正负,指数部分决定了数值的大小,小数有效位部分决定了数值的精度- 一个数在 JavaScript 内部实际的表示形式 (-1)符号位 1.有效位 2 指数位
- 精度最多 53 个二进制位, -(253-1)到 253-1
- 指数部分最大值是 2017(211-1),分一半表示负数,JavaScript 能够表示的数值范围是 21024~2-10

