WEB学习进阶之路 - 位移运算和补码
在WEB前端全栈成长计划(二阶段)第二章中,集中讲了运算符
但是对于真正了解并能准确进行 位运算,本博文深入讨论左移,右移,无符号右移,以便我自己和同学共同学习进步。
补码
补码是在计算机存储数值的方式,因为这样可以是符号位和数值位一起运算,并且可以将减法和加法统一处理为加法运算,例如 2 - 1 = 2 + (-1)
补码是怎么来的呢?
在计算机中,有最大可以处理的位数,比如常用的32位计算机,64位计算机
比如对于一个时钟, 现在是6点,想要把现在的时间改为3点可以有两种方式
6 -3 = 3即将时钟向后拨3个小时
6 + 9 = 6 + (12 - 3) 即将时钟向前拨动9个小时
12就是时钟的最大值,而在32位计算机中,最大值就是 1111 1111 1111 1111 1111 1111 1111 1111
让时钟中重回原点,加1就行了,变成了 1 0000 0000 0000 0000 0000 0000 0000 0000
由于计算机只能处理32位,所以最高位被丢弃了,那么很神奇,他又回来了。类似时钟一样的圆圈,又回到起始点了
比如3的补码计算过程就是
3的二进制数据 0000 0000 0000 0000 0000 0000 0000 0011
用最大值减去3的二进制,得到 1111 1111 1111 1111 1111 1111 1111 1100
讲解过加1,让其回到原点,得到1111 1111 1111 1111 1111 1111 1111 1101
这个里面有个概念”取反“,取反起始就是用最大值减去当前值,从结果也可以看出,也就是想要位置0和1交换
位移运算
以下通过手动写入的的方式讲明白位移是如何进行的
首先将数据转换为32位的二进制数据,然后进行位运算,将得到的结果转为10进制数据后返回。
1. 与运算
5 & 1
5的二进制数据 0000 0000 0000 0000 0000 0000 0000 0101
1的二进制数据 0000 0000 0000 0000 0000 0000 0000 0001
按位进行与运算,相同位都为1,则返回1,否则返回0
得到结果
0000 0000 0000 0000 0000 0000 0000 0001
转换为10进制,得到1
| 或运算,^ 异或运算,! 非运算都是和上述逻辑相同,这里就不再赘述
2. 左移运算 <<
将二进制的数据向左移动,32位长度不变,右边补充0
5 << 1
5的二进制数据 0000 0000 0000 0000 0000 0000 0000 0101
左移1位
0000 0000 0000 0000 0000 0000 0000 1010 转换为10进制得到结果 10
左移2位
0000 0000 0000 0000 0000 0000 0001 0100 转换为10进制得到结果 20
得到左移运算的算式表达
n << m = n * 2^m
3. 右移运算 >> 也叫有符号右移
有符号右移:最右侧移除的数据丢弃,左侧根据符号位(最高位)的符号决定补值,当高位为1(负值)时,高位补1;当高位为0(正值)时,高位补0;
12 >> 2
12的二进制数据
0000 0000 0000 0000 0000 0000 0000 1100
右移2位
0000 0000 0000 0000 0000 0000 0000 0011
得到结果转为10进制 3
移动3位时,得到1
得到当值为正数时,右移运算表达式
n >> m == Math.floor(n / 2^m)
-12 >> 2
-12的二进制数据
1000 0000 0000 0000 0000 0000 0000 1100
在进行补码操作,除过符号位,其余位取反加1
取反
1111 1111 1111 1111 1111 1111 1111 0011
加1
1111 1111 1111 1111 1111 1111 1111 0100
其实这里有个快速算法,从右开始,第一个1保留,其余全部取反。
右移2位,根据右移法则,由于符号位位1,所以最高位补1,得到
1111 1111 1111 1111 1111 1111 1111 1101
在进行补码运算,使用快速算法,得到
1000 0000 0000 0000 0000 0000 0000 0011
转换为10进制得到 -3
4. 无符号右移 >>>
无符号右移,是不论最高位的正负的,丢弃右边低位,左边高位补0
-12 >>> 2
-12的二进制数据
1000 0000 0000 0000 0000 0000 0000 1100
补码
1111 1111 1111 1111 1111 1111 1111 0100
右移2位
0011 1111 1111 1111 1111 1111 1111 1101
这里需要主要,因为最高位是正数(0),无需补码运算了(因为正数的补码就是本身)。
转换为10进制得到 1073741821
在计算时为什么要补码
这是因为在设计计算机时,尽量让计算机做简单的运算,不需要考虑符号位,如果要考虑符号位,计算机的设计就要复杂很多。
所以在计算时,让符号位也参与运算,另外减法可以变为加法, 如 1 - 1可以变为 1 + (-1),于是聪明的人类通过设计
反码和补码的形式让计算机即设计简单,又能正确运算算式了。
扩展知识点:
1. 在JS中十进制转二进制
function dec2Bin(num) {
console.log((num >>> 0).toString(2));
}
2. 在JS中二进制转十进制
function bin2Dec(num) {
console.log(parseInt(num, 2).toString(10));
}
- 点赞
- 收藏
- 关注作者
评论(0)