【回顾】原码、反码和补码
重新梳理回忆下原码、反码和补码相关的知识,自己总是记混
基本概念
- 机器数
- 真值
- 原码
- 反码
- 补码
机器数
一个数在计算机中的表示形式, 叫做这个数的机器数。计算机是由二进制数字电路构成的,所以机器数只能由二进制数码0和1来表示。
机器数带有符号,符号存放在最高位,正数用 0 表示,负数用 1 表示。
例:
1 | // [] 中的表示符号位 |
真值
机器数对应的真实数值即为机器数的真值。
例:
1 | // [] 中的表示符号位 |
原码
人最容易理解和计算的方式
符号位 + 真值的绝对值 = 原码
以 8 位 二进制为例
1 | // [] 中的表示符号,剩下的为真值的绝对值 |
反码
正数的反码是其本身。
1 | +1 的原码:[0]0000001,反码:[0]0000001 |
负数的反码:在原码的基础上,符号位不变,其余位取反(即0变1,1变0)
。
1 | -1 的原码:[1]0000001,反码:[1]1111110 |
负数的反码:也可以由对应的补码减1得到
。
1 | -1 的补码:[1]1111111,反码:[1]1111110 |
如果一个反码表示负数,通常需要先转换成原码
补码
正数的补码就是其本身
1 | +1 的原码:[0]0000001,反码:[0]0000001,补码:[0]0000001 |
负数的补码:在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
1 | -1 的原码:[1]0000001,反码:[1]1111110,补码:[1]1111111 |
如果一个补码表示负数,通常需要先转换成原码
JS 中的位操作符
ECMAScript 中的所有数值都以 IEEE 754 64 位格式存储,但位操作并不直接应用到 64 位表示,而是先把值转换为 32 位整数,再进行位操作,之后再把结果转换为 64 位。
有符号整数使用 32 位的前 31 位表示整数值,第 32 位表示数值的符号。
按位非( ~ )
返回数值的补码
1 | let num1 = 25; // 二进制 00000000000000000000000000011001 |
由上看出:按位非的最终效果是对 数值取反并减 1
,即 -25 - 1 = -26;
(虽然最后结果相同,但是位操作速度快得多)
按位与( & )
按位与需要有两个操作数
将两个操作数的每一位对齐,然后按下表的规则,对每一位执行「与」操作
第一个数值的位 | 第二个数值的位 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
例:
1 | let result = 25 & 3; |
结论:按位与操作在两个位都是 1 时返回 1,在任何一位是 0 时返回 0。
按位或( | )
按位或需要有两个操作数
将两个操作数的每一位对齐,然后按下表的规则,对每一位执行「或」操作
第一个数值的位 | 第二个数值的位 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
1 | let result = 25 | 3; |
结论:按位或操作在两个位都是 0 时返回 0,在任何一位是 1 时返回 1。
按位异或( ^ )
按位异或需要有两个操作数
将两个操作数的每一位对齐,然后按下表的规则,对每一位执行「异或」操作
第一个数值的位 | 第二个数值的位 | 结果 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
例:
1 | 25 = 0000 0000 0000 0000 0000 0000 0001 1001 |
结论:按位异或操作只在一位上是 1 的时候返回 1(两位都是 1 或 0,则返回 0)。
左移( << )
左移多少位就在这个二进制数的右边加多少个0来补位
注意:左移会保留所操作数值的符号,即 -2 左移 5 位,得到的是 -64,而不是 +64
例:
1 | let v = 2 // 二进制数为 10 |
有符号右移 ( >> )
右移多少位就在这个二进制数的左边「符号位后面」加多少个0来补位
注意:符号位不变,补位的 0 添加在符号位后面
例:
1 | let v = 64 // 二进制数为 00000000 00000000 00000000 01000000 |
无符号右移 ( >>> )
对于正数,无符号右移与 有符号右移结果相同。
对于负数,右移多少位就在这个二进制数的左边加多少个0来补位,符号位会被忽略而被0补上。
注意:对于负数,符号位是会改变的,补位的 0 添加在符号位前面
1 | let v = -64 // 二进制数为 11111111 11111111 11111111 11000000 |