一、无符号数和有符号数
在学习本届内容开始之前,是默认学过二进制、八进制、十进制和十六进制之间的转化和表示的;在计算中,我们都知道其内部都是一连串的01二进制数字,而这一部分的内容我们就是要研究如何将我们实际生活中数字以二进制形式存储在计算中,同时在计算中实现数的运算(加减乘除等);接下去我们首先学习的是数字在计算机中的几种不同的表现形式。
1)无符号数字
顾名思义,就是在计算中这个数字没有符号,则其实也就是默认为该数只能是正数,寄存器的位数就可以直接反应出数值能表示范围的大小
对于8位的寄存器,该8位全部用于表示数值,所以能表示的范围就是0到
255
=
2
8
−
1
255=2^{8}-1
255=28−1;对于16位寄存器,范围就是0到
65535
=
2
16
−
1
65535=2^{16}-1
65535=216−1。
2)有符号数
就是所表示的数值具有符号位,即有符号数,那在机器中又如何表示符号呢?由于正负号就两个,所以也可以使用01来表示正负号,我们可以先来看一下一些真值如何在机器中表示。
①真值和机器值
不难看出,只要在计算机中规定好数值的第一位是数值的符号位,0表示正数,1表示负数;同时对于小数的表示,其小数点是隐含在符号位的后面,对于整数,其小数点隐含在数值的尾部,所以对于给出一个有符号数,对于其表示为计算机中存储的数值而言,操作很简单,计算中只要规定符号位在首部,0表示正数,1表示负数。
②原码
原码表示法如下,其定义如图所示,其实我们在理解原码表示法的时候完全没有必要通过给出的定义来理解原码表示法,其实所谓的原码表示法,就是上面刚学过的将一个真值表示为机器数,也就是将符号位用01来表示。
对于+1110 其原码就是将+用0来表示即其原码为
[
x
]
原
=
0
,
1110
[x]_{原}=0,1110
[x]原=0,1110,同时呢我们在书写的时候,应加上一个,号,以区分开符号位和数值,而实际在计算中存储的时候是没有,的,直接规定哪一位为符号位。
尝试来看下定义(假设寄存器个数为n+1位,n位是数值位)
①:对于真值的范围在
[
0
,
2
n
)
[0,2^n)
[0,2n)之间,也就是说当所要表示的值在寄存器所能表示的最大范围内且是大于等于零的数,该原码就可以表示为
0
,
x
0,x
0,x的形式,也就是符号位取0,数值位抄下来。
②:对于真值的范围在
(
−
2
n
,
0
]
(-2^n,0]
(−2n,0],也就是说所要表示的真值要大于所能表示的最小值且是小于等于零的,则该原码就可以表示为
[
x
]
原
=
2
n
−
x
[x]_{原}=2^n-x
[x]原=2n−x的形式;由于
x
x
x为负数,减去负数为加上这个数的数值部分,加上
2
n
2^n
2n实际也就是添加上了符号位1。
上面的例子是原码表示整数,那对于小数呢?
对于小数来说其和整数的原码表示方法是很一致的,符号位0表示正的,1表示负的,在书写的时候,对于小数,使用的 . 来分隔开。
尝试来看下定义(假设寄存器个数为n+1位,n位是数值位)
①:对于小数真值其在
[
0
,
1
)
[0,1)
[0,1)之间,该原码就可以表示为
[
x
]
原
=
0
,
x
[x]_{原}=0,x
[x]原=0,x的形式,也就是符号位取0 . ,然后数值位抄下来。
②:对于真值的范围在
(
−
1
,
0
]
(-1,0]
(−1,0],该原码就可以表示为
[
x
]
原
=
1
−
x
[x]_{原}=1-x
[x]原=1−x的形式;由于
x
x
x为负数,减去负数为加上这个数的数值部分,即1加上
∣
x
∣
|x|
∣x∣,实际也就是添加上了符号位1。
③补码
前面了解的原码表示法就是其真值实际存储在计算机的一种形式,但是在计算机中也不仅仅只有这一种形式来表示实际中的真值,还有补码表示,反码表示,以及移码表示,接下去,我们会继续学习以下几种表示方法。
补码是什么样的,为什么要学习补码?补码的作用是什么?为什么原码表示不够,还要引进一个补码表示?
补的概念
对于下图中的一个时钟,现在时针的指向的是6,若我现在像将时针指向3的位置,该如何转动时针?
- 方法一:即将6减3,就是逆时针转动3格就可以回退到想要的3的位置。
- 方法二:即将让6+9,就是顺时针转动9格就可以转到3的位置上。
其实我们就可以总结出来,对于时钟这种计数方式来说,让 6 − 3 6-3 6−3的效果和让 6 + 9 的效果是一致的 6+9的效果是一致的 6+9的效果是一致的,当 6 + 9 = 15 6+9=15 6+9=15时,就会自动的进行mod12的运算从而得到数字3;进而引出来了补数的概念,对于时钟以12为模来说,其 − 3 -3 −3的补就是 9 9 9,即一个数想减去一个数,即可以通过这个数加上这个数的补数就可以得到正确的值。
而对于计算来说其存储数据也是具有该功能的!对于4个寄存器来说,其就是一个以16为模的计数器,比如1111加上0001后其实是10000,但是只有四个寄存器,就会自动的舍弃掉前面的1,从而是0000,10000是十进制的16,模16之后就是0了,自动的会进行模16操作,所以对于我们在计算中实现减法的就可以变得非常简单,减去一个数就是加上这个数的补码就可以得到结果。
补码的定义和求补码
先不看补码的定义,直接给出计算补码的简便算法,对于正数的补码,其补码等于原码,对于负数,其补码为在原码的的基础上符号位不变,按位取反末尾加一就可以得到负数的补码。
理解以下补码的定义(假设寄存器个数为n+1位,n位是数值位)
①:定义指出当
x
x
x在
[
0
,
2
n
)
[0,2^n)
[0,2n)之间时,即都为正数,且小于所能表示的最大数值,其补码的形式就是原码的形式
0
,
x
0,x
0,x。
②:当
x
x
x在
[
−
2
n
,
0
)
时候
[-2^n,0)时候
[−2n,0)时候,其补码形式表示为
2
n
+
1
+
x
2^{n+1}+x
2n+1+x。例如上图中所要表示的
x
=
−
1011000
x=-1011000
x=−1011000,n为7,即数值位为7位,该数值的原码为
1
,
1011000
1,1011000
1,1011000根据定义可得其补码为
2
7
+
1
=
1
0000
0000
−
1011000
=
1
,
0101000
2^{7+1}=1~0000~0000-1011000=1,0101000
27+1=1 0000 0000−1011000=1,0101000;现在我们在按着简便方法来计算一下该补码,先除去符号位按位取反得到
1
,
0100111
1,0100111
1,0100111,再末位加一得到
1
,
0101000
1,0101000
1,0101000,和使用定义求到的一致。
对于小数呢?
④反码
反码对于正数来说,其反码就是等于其原码的,对于负数来说,其反码就是在原码的基础上符号位不变,按位取反,不再进行末位加一,所以如下定义几乎和补码一样,对于负数反码的定义就是加了一个1,因为补码是减了1,所以只在定义基础上减一个1就可以得到反码。
对于小数来说,也是类似。
⑤原码、补码、反码表示范围对比
对于机器数长为8位,其中符号位占一位,对于整数来说,其原码,补码,反码,以及无符号数的表示范围。
- 无符号数:8位的无符号数,其能表示的范围是从0到 2 8 − 1 = 255 2^{8}-1=255 28−1=255
- 原码表示:符号位占一位,数值位为7位,所以范围是 [ − 2 7 + 1 = − 127 , 2 7 − 1 = 127 ] [-2^{7}+1=-127,2^7-1=127] [−27+1=−127,27−1=127]。
- 补码表示: [ − 2 7 = − 128 , 2 7 − 1 = 127 ] [-2^7=-128,2^7-1=127] [−27=−128,27−1=127],为什么补码会多表示一个-128,其原因如下;我们可以尝试计算一下+0和-0的原码,分别是 0 , 000 0000 0,000~0000 0,000 0000和 1 , 000 0000 1,000~0000 1,000 0000,再将都妆化为补码,可以发现都是 0 , 000 0000 0,000~0000 0,000 0000,而对于 1 , 000 0000 1,000~0000 1,000 0000这串二进制看作是补码的话,其原码为 1 , 1000 0000 1,1000~0000 1,1000 0000,最高位的1应该是要被舍弃的,若舍弃的话就会变成-0;这时候诡异的事情就发生的,-0转化为补码会变为 0 , 000 0000 0,000~0000 0,000 0000,根本转化不到 1 , 000 0000 1,000~0000 1,000 0000,为了避免这种情况,就让 1 , 000 0000 1,000~0000 1,000 0000多表示一位数-128,让-0和正0的补码都为 0 , 000 0000 0,000~0000 0,000 0000。
- 反码表示,其范围是 [ − 127 , + 127 ] [-127,+127] [−127,+127]。
⑥移码
由于采用补码表示数值的时候,其是很难直观的就可以看出来哪个数据大,哪个数据小,所以就有引进了移码,其实所谓的移码,就是让数值都偏移相同的单位,然后再来比较;同时需要注意的是,移码只用于表示整数的,其是再补码的基础上,将其符号位取反就行。
对于x的移码,其移码就为 x + 2 n x+2^n x+2n;