我们想一下 区分正负数 最好的办法就是加一个符号位
这就是 “符号与幅值表示法” 英文是sign and magnitude
这样的话 那8-bits 位宽举例 符号位0为正数 1为负数:
0000 0011 = 310 — 10进制的3 1000 0011 = -3 10 – 10进制的-3 也就1~7位是幅值 第八位是符号位这种方法比较直观 但是没法用
你试着加减一下 就发现需要很多工作要做
计算机性能就被拖累在每一次加减运算了
于是我们的先辈想了另一种方法:反码
反码反码的思路来源于 进行减运算的时候 一旦借位 前面的所有0 都变成1 1变成0
比如 我拿0(其实是正零 后面再说 现在来个剧透)举例
发现没有 这个计算机可以直接算 不需要像第一种方法有多余的步骤
当然 计算机将所有运算都化为 加法运算 所以:
实际上运算是这样的:
-1 就是 1 按位取反后的结果 这就是“反码” 或者说“取x的反码” 的含义 :按位取反
由此 我们知道 反码表示法中(8位):
最大的正数 0111 1111 绝对值最大的负数 1000 0000 绝对值最小的负数 1111 1111 = “负零” 010 绝对值最小的正数 0000 0000 = “正零” 010不要想当然 第1~7位不再是“幅值” ,也就不是通过位权简单加起来完事了的
但是反码带来很大的问题
没有解决第一种方法的 两个零问题(正零 负零) 运算不方便(你可以试试)你发现 数的符号是确定的 但是如何进行二进制转十进制 就变得比较麻烦
因为第1~7位不再是“幅值” 需要补一个1才行
这就是下一轮的改革:补码
补码上过课的同学都知道 补码表示法中
我要想获得一个数的负数(1与-1) 只需要先求那个数的反码 再加1就行
其实实质上就是上面所说的 因为反码不靠谱 计算机识别数的大小很麻烦 而且还有双零问题
所以我们加个1
仅此而已
这样操作以后 我们发现 识别数字大小变的简单 自然转别的进制也变得简单:
例如:
注意 符号位用的是负号
这里针对补码表示法 也间接说明补码的好处
所谓符号拓展 就是16位数转为32位(比自己位宽大的)的时候的运算套路
很明显 多余的位 也就17位到32位 都是没有信息 自动补足的
我们看个例子:
这种有点无脑其实 直接用符号位补足第17~32位
原理就是 减法借位 前面的0都变成1 1都变成1 之前说了
所谓 补码 反码 符号与幅值 就是三个解决正负数表示 运算的三个方法
名称 | 实质 | 获取负数形式方法 |
---|---|---|
符号与幅值(sign and magnitude) | 解决方法ver1.0 | 把某一位作为符号位 然后符号位取反 |
反码(one’s complement) | 解决方法ver2.0 | 按位取反 |
补码(two’s complement) | 解决方法ver3.0 | 按位取反 再加1 |
最后 可能你还感兴趣别的内容 这里来几个传送:
想学习数据库嘛? 不妨从MySQL入手
MySQL专栏
python这么火 想要深入学习python 玩一下简单的应用嘛?可以看我专栏 还在持续更新中哦:
python应用
小孩子才做选择 大人全都要!对后端感兴趣吗?收下它吧:)
手把手带你学后端(服务端)
目前在Django框架学习阶段