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]
~取反运算( 0 变 1,1 变 0)
- 取反在减一
js
~0=1
~1=0
~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======取出整数部分1
8进制转二进制
- 8进制0-7,0作为开头
- 一个八进制,占三位
js
// 八进制对应的二进制表现方式
let a = 016 // 001 110
let b = 0123 // 001 010 011
10进制转二进制
- 整数部分: 除 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 1111
2进制转8进制
- 三个位代表一个8进制
js
let a = 001110 // 001 110 => 016
let b = 001010011 // 001 010 011 => 0123
2进制转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