WEB学习进阶之路 - 位移运算和补码

举报
sujrexia 发表于 2020/07/15 16:14:45 2020/07/15
【摘要】 在WEB前端全栈成长计划(二阶段)第二章中,集中讲了运算符但是对于真正了解并能准确进行 位运算,本博文深入讨论左移,右移,无符号右移,以便我自己和同学共同学习进步。位移运算以下通过手动写入的的方式讲明白位移是如何进行的首先将数据转换为32位的二进制数据,然后进行位运算,将得到的结果转为10进制数据后返回。5 & 15的二进制数据 0000 0000 0000 0000 0000 0000 0...

WEB前端全栈成长计划(二阶段)第二章中,集中讲了运算符

但是对于真正了解并能准确进行 位运算,本博文深入讨论左移,右移,无符号右移,以便我自己和同学共同学习进步。

补码

补码是在计算机存储数值的方式,因为这样可以是符号位和数值位一起运算,并且可以将减法和加法统一处理为加法运算,例如 2 - 1 = 2 + (-1)

补码是怎么来的呢?

在计算机中,有最大可以处理的位数,比如常用的32位计算机,64位计算机

比如对于一个时钟, 现在是6点,想要把现在的时间改为3点可以有两种方式

  1. 6 -3  = 3即将时钟向后拨3个小时

  2. 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));

}


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。