符号位;原码,反码,补码
1 符号位
计算机如何存储数据,因为计算机世界⾥⾯所有的数据归根结底都是由0和1来存储的,那么如何表达数值的正负呢?只知道书本上说是有⼀个符号位,当该符号位为0时,表⽰的是正数,为1时表⽰负数。我那时没搞懂为什么这样规定,我觉得1么,代表正数挺合理的,那么0就⾃然表⽰负数咯,所以不解,只能死记硬背:0正1负。
当代绝⼤多数计算机表⽰浮点数都是采⽤IEEE标准的,这⾥简化⼀下,我们只关⼼符号位,那么对于⼀个数,计算机其实是以下⾯的式⼦来描述它的:(-1)s×X,这⾥的指数s就是⽤来决定数值X是正数还是负数,显⽽易见,当s=0时,则X为正数(因为任何数的0次幂都是1),当s=1时,则X为负数(因为-1的1次幂为-1),⾄此我们就理解了为什么符号位为0时表⽰正数,为1时表⽰负数啦。
2 机器数
⼀个数在计算机中的⼆进制表⽰形式,叫做这个数的机器数。机器数是带符号的,在计算机⽤⼀个数的最⾼位存放符号,正数为0,负数为1.⽐如,⼗进制中整数+3,若计算机字长为8位,转换为⼆进制数为 0000 0000 0000 0000 0000 0000 0000 0011;如果是-3,就是1000 0000 0000 0000 0000 0000 0000 0011。
3 真值
因为第⼀位是符号位,所以机器数的形式值就不等于真正的数值。
例如:有符号数的真值如下
1000 0000 0000 0000 0000 0000 0000 0011的真值 = -000 0000 0000 0000 0000 0000 0000 0011 = -3;
0000 0000 0000 0000 0000 0000 0000 0011的真值 = +000 0000 0000 0000 0000 0000 0000 0011 = +3
4 原码,反码,补码的基础概念和计算⽅法
对于⼀个数,计算机要使⽤⼀定的编码⽅式进⾏存储,原码,反码,补码都是机器存储⼀个具体数字的编码⽅式。
原码
原码就是⽤第⼀位表⽰符号,其余位表⽰值,⽐如如果是32位⼆进制:
[+3]原码 = 0000 0000 0000 0000 0000 0000 0000 0011
[-3]原码 = 1000 0000 0000 0000 0000 0000 0000 0011
负数二进制补码运算法则 因为第⼀位是符号位,所以32位⼆进制整数的取值范围就是:
[1111 1111 1111 1111 1111 1111 1111 1111 , 0111 1111 1111 1111 1111 1111 1111 1111] ==> [-2147483647, 2147483647]
反码
反码的表⽰⽅法是:
*正数的反码是其本⾝
*负数的反码是在其原码的基础上,符号位不变,其余各个位取反
-3 原码 1000 0000 0000 0000 0000 0000 0000 0011
反码 1111 1111 1111 1111 1111 1111 1111 1100
+3 原码 0000 0000 0000 0000 0000 0000 0000 0011
反码 0000 0000 0000 0000 0000 0000 0000 0011
补码
补码的表⽰⽅法是:
*正数的补码就是其本⾝
*负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1(即在反码的基础上+1)
-3 原码 1000 0000 0000 0000 0000 0000 0000 0011
反码 1111 1111 1111 1111 1111 1111 1111 1100
补码 1111 1111 1111 1111 1111 1111 1111 1101
+3 原码 0000 0000 0000 0000 0000 0000 0000 0011
反码 0000 0000 0000 0000 0000 0000 0000 0011
补码 0000 0000 0000 0000 0000 0000 0000 0011
5. 为何要使⽤原码, 反码和补码
计算机可以有三种编码⽅式表⽰⼀个数. 对于正数因为三种编码⽅式的结果都相同:
以下以8位机器为例
[+1] = [00000001]原 = [00000001]反 = [00000001]补
所以不需要过多解释. 但是对于负数:
[-1] = [10000001]原 = [11111110]反 = [11111111]补
可见原码, 反码和补码是完全不同的. 为何还会有反码和补码呢?
⾸先, 因为⼈脑可以知道第⼀位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减. (真值的概念在本⽂最开头).
但是对于计算机, 加减乘数已经是最基础的运算, 要设计的尽量简单. 计算机辨别"符号位"显然会让计算机的基础电路设计变得⼗分复杂! 于是⼈们想出了将符号位也参与运算的⽅法.
根据运算法则减去⼀个正数等于加上⼀个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法⽽没有减
法, 这样计算机运算的设计就更简单了.
于是⼈们开始探索将符号位参与运算, 并且只保留加法的⽅法. ⾸先来看原码:
计算⼗进制的表达式: 1-1=0
为了解决原码做减法的问题, 出现了反码:
1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0
发现⽤反码计算减法, 结果的真值部分是正确的. ⽽唯⼀的问题其实就出现在"0"这个特殊的数值上. 虽然⼈们理解上+0和-0是⼀样的, 但是0带符号是没有任何意义的. ⽽且会有[0000 0000]原和[1000 0000]原两个编码表⽰0.
于是补码的出现, 解决了0的符号以及两个编码的问题:
1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原
这样0⽤[0000 0000]表⽰, ⽽以前出现问题的-0则不存在了.⽽且可以⽤[1000 0000]表⽰-128:
(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补
-1-127的结果应该是-128, 在⽤补码运算的结果中, [1000 0000]补就是-128. 但是注意因为实际上是使⽤以前的-0的补码来表⽰-128, 所以-128并没有原码和反码表⽰.(对-128的补码表⽰[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)
使⽤补码, 不仅仅修复了0的符号以及存在两个编码的问题, ⽽且还能够多表⽰⼀个最低数. 这就是为什么8位⼆进制, 使⽤原码或反码表⽰的范围为[-127, +127], ⽽使⽤补码表⽰的范围为[-128, 127].
部分内容转载⾃别处。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论