简介
我们先来了解一个概念:
在机器内,一个数的表达形式称为“机器数”,
而这个数所代表的数值称为此机器数的“真值”
我们的计算机使用的是二进制编码,
可以把数据很好的存储起来。
而数据又分为正和负两种,
那么正负号怎么在计算机内表示呢?
在一般情况下,
我们用 0 来表示正号
用 1 来表示负号
计算机的二进制只有0和1两个数
而符号位要放在最高位,可以清晰地看出来,
我们拿 +3 和 -3 来举例:
+3: 011
-3: 111
最左侧的数表示的就是符号位
他们会和数据本身一起组合成一个数,我们进行进制转换计算的时候把最左边的数据给忽略就行。
一个数值信息再计算机内采用符号数字化处理后,计算机就可以识别和表示数符了。
但是为了改进符号数的运算方法和简化运算器的硬件结构,
人们研究出了符号数的多种二进制编码方法,
他们的实质就是对负数表示的不同编码。
分别为:原码、反码和补码。
原码
概念:将符号位数字化为0或1,
数的绝对值与符号一起编码,
即所谓的“符号-绝对值表示”的编码,
称为原码
就是上面简介里面介绍的方法,就是最初的变换,只加了一个符号位。
这个图表示的就是在一个字节内存放一个整数时的源码表示,注意,这里只是整数
像 “【X】原” 这样的表示方法代表的就是机器数,X称为机器数的真值。
对于一个带符号的纯小数,我们的表示方法有了些许的不同,
这个的原码表示方法就是把小数点左边的那一位用来表示符号,注意,这里说的是纯小数。
这种原码的表示方法还是很简单的,而且和真值间的转换也是比较方便的,
但是原码的表示也是存在着一些问题的。
第一个就是 0 的表示不唯一。
对于一个 0 的表示方法,不说正负,单是位数就是不确定的
![在这里插入图片描述](https://img-blog.csdnimg.cn/e3ddeb46d18540cbb99ff2285ee5bb24.png#pic_center
这上面就很好的诠释了。
这个是因为 0 具有二义性,就是可正可负,会给机器的判零带来麻烦。
第二个是因为原码在进行四则运算时,符号位需要单独处理,且运算规则复杂。
就比如说加法运算
同号相加符号不变
异号相加符号不确定,
而我们的减法在运算时还会有“借位”这种操作,
这个操作在计算机中是很难实现的,
也就需要开发出其他的编码方法。
反码
反码很少使用,它是原码和补码之间的中间码,可以当作桥梁来使用。
这个反码是可以按照正负来分的
对于正数而言,它的反码和原码的表示是相同的。
而负数就不一样了,
对于负数而言,其反码的符号位与原码的符号位相同,就是说都为1,
而其他位都按位取反,也就是 0 变 1 , 1 变 0 .
像如下:
[X]原=11100110 11100110 [X]反=10011001
在反码中, 0 的表示方法也是不唯一的
纯小数的变换也是小数点前 0 为正, 1 为负
正数小数点后不变,
负数小数点后按位取反。
补码
这个补码相对而言还是难以理解的。
在说补码之前,我们先来说一下“模数”
模数从物理意义上来讲,是某种计量器的容量。
像是钟表,模数就是12,每12个点开启一个循环,在12要进一位的时候扔掉原来的12,变为1
在数学上可以看成是取余数的运算。
在C语言中,它的符号就是“%”
比如:
13 % 12 = 1
以下会引出补码
在模数系统中,
8 - 2 = 8 + 10
模数为12
他这个条件的成立是因为 2 与 10 对于模数是互为补数的
即2 + 10 = 12
由此,我们得出一个结论
在模数系统中,一个数减去另一个数,
或者说一个数加上一个负数,
等于第一个数加上第二个数得补数
如下
8 + ( - 2)= 8 + 10 模数为12
这里的10称为 - 2在模12下的“补码”
当负数采用补码表示后,可以使加减法统一为加法运算。
在计算机中,使用的是二进制
看我们的第一位
----------0
----------1
第一位可以存放两个数
家伙是那个第二位
------10
------11
此时可以存放四个数
也就是说,每多出一位可以存放2的n次方个数
n表示位数
那么我们存储一个数,每多一位,它的模都会变化,
如果有n位正数,那么它的模就是2的n次方
如果有n位小数,那么存储时,小数点前一位为符号位,模数为2
对于负数的补码的表示,我们采用模数与真值的相加
如:
[X] = - 0110 [X]补 = 2的4次方 + ( - 0110)=1010
对于一个负数,其补码由该数的反码的末位加 1 求得。
对于正数来说,其原码、反码、补码的形式相同
补码的特点之一就是0的表示唯一
这个了解就行
就是取模了
对于补码的运算规则,相对而言是最简便的
在这里,符号位是可以参与运算的,作为数值参与
得出的结果的符号也是正确的,符号不需要单独处理
其次,减法运算可转化成加法,不需要考虑借位的问题了
我们来看一下67 - 10的运算
补码运算的结果仍为补码
结果为正,就相当于是原码
结果为负,进行原码到补码的逆运算就能得出原码。
当然,运算并不一定是正确的,如果结果超出了数的范围,就会出现“溢出”
导致错误,
本篇内容到此结束