本系列文章是学习了网课《哈尔滨工业大学–计算机组成原理》之后,用以梳理思路而整理的听课笔记及相关思维拓展。本文涉及到的观点均为个人观点,如有不同意见,欢迎在评论区讨论。
无符号数和有符号数
无符号数的每一位都用来存放数值,有符号数需要留出一位用作符号。
将符号位数字化,放在有效数字前面,就组成了有符号数。
将符号“数字化”的数称为机器数,把带“+”或“-”符号的数称为真值。
这种符号和数值的组合形成了一种编码,但是这种编码方式的机器数能否用于数学运算需要分析。
下面介绍几种编码方式:
原码表示法
符号位为0时表示正数,符号位为1时表示负数。
整数的原码定义:
[
x
]
原
=
{
0
,
x
,
2
n
>
x
≥
0
2
n
−
x
,
0
≥
x
>
−
2
n
[x]_原 = \begin{cases} 0, x,2^n > x \geq 0 \\ 2^n - x,0 \geq x > -2^n \end{cases}
[x]原={0,x,2n>x≥02n−x,0≥x>−2n
式中,x为真值,n为整数的位数。
举例
x = + 1110,表示为0,1110
x = - 1110,表示为1,1110
小数的原码定义:
[
x
]
原
=
{
x
,
1
>
x
≥
0
1
−
x
,
0
≥
x
>
−
1
[x]_原 = \begin{cases} x,1 > x \geq 0 \\ 1 - x,0 \geq x > -1 \end{cases}
[x]原={x,1>x≥01−x,0≥x>−1
式中,x为真值。
举例
x = +0.1101,表示为0,1101
x = -0.1101,表示为1,1101
原码方式虽然易于表示,但是进行加减运算时,有许多麻烦。也就是说这种编码方式在运算上有缺陷。
例如:
两个操作数符号不同,在进行加法运算时,用绝对值大的数的绝对值减去绝对值小的数的绝对值,符号以绝对值大的数为准,不然会溢出造成计算错误。
如果能够将加减法运算统一,将会减少计算的步骤与时间,需要找到负数对应的正数,然后将减法操作用加法代替。当机器数采用补码时,可以满足要求。
补码表示法
补码用到了补数的概念,补数就像时钟一样,时钟当前指向6,想让它指向3,可以顺时针转9个小时到3,也可以逆时针转3个小时到3。那么也就是以12为模,+9是-3以12为模的补数。只要确定了模,就可以找到与负数等价的正数。
那这样就可以把减法运算当加法运算来做了。
例如,我们要做9 - 5
做减法,9 - 5 = 4,但是机器内部要根据绝对值确定符号,然后再相减。
做加法,9 - 5 = 9 + (7)= 16 mod 12 = 4
基于这个概念,设计补码这种机器数。
整数补码的定义:
[
x
]
补
=
{
0
,
x
,
2
n
>
x
≥
0
2
n
+
1
+
x
,
0
>
x
≥
−
2
n
(
m
o
d
2
n
+
1
)
[x]_补 = \begin{cases} 0,x,2^n > x \geq 0 \\ 2^{n+1} + x,0 > x \geq -2^n (mod 2^{n+1}) \end{cases}
[x]补={0,x,2n>x≥02n+1+x,0>x≥−2n(mod2n+1)
式中,x为真值,n为整数的位数。
x = +1010时
[ x ] 补 = 0 , 1010 [x]_补 = 0,1010 [x]补=0,1010
x = -1101时
[ x ] 补 = 2 n + 1 + x = 100000 − 1101 = 1 , 0011 [x]_补 = 2^{n+1} + x = 100000 - 1101 = 1,0011 [x]补=2n+1+x=100000−1101=1,0011
小数补码的定义:
[
x
]
补
=
{
x
,
1
>
x
≥
0
2
+
x
,
0
>
x
≥
−
1
(
m
o
d
2
)
[x]_补 = \begin{cases} x,1 > x \geq 0 \\ 2 + x,0 > x \geq -1 (mod 2) \end{cases}
[x]补={x,1>x≥02+x,0>x≥−1(mod2)
式中,x为真值,n为整数的位数。
x = +0.1001时
[ x ] 补 = 0 , 1001 [x]_补 = 0,1001 [x]补=0,1001
x = -0.0110时
[ x ] 补 = 2 + x = 10.0000 − 0.0110 = 1 , 1010 [x]_补 = 2 + x = 10.0000 - 0.0110 = 1,1010 [x]补=2+x=10.0000−0.0110=1,1010
但是这看着又有减法了,实际上可以化简
[ x ] 补 = 2 5 + x = 11111 + 00001 − x 1 x 2 x 3 x 4 = 1 x 1 ‾ x 2 ‾ x 3 ‾ x 4 ‾ [x]_补 = 2^5 + x = 11111 + 00001 - x_1x_2x_3x_4 = 1 \ \overline{x_1} \ \overline{x_2} \ \overline{x_3} \ \overline{x_4} [x]补=25+x=11111+00001−x1x2x3x4=1 x1 x2 x3 x4 + 00001
相当于对于负数- x 1 x 2 x 3 x 4 x_1x_2x_3x_4 x1x2x3x4的原码为1 x 1 x 2 x 3 x 4 x_1x_2x_3x_4 x1x2x3x4,对原码符号位以外取反,末位加一,就可以求的负数的补码。
反码表示法
通常用来作为原码求补码或者由补码求原码的中间过渡。
整数反码的定义:
[
x
]
反
=
{
0
,
x
,
2
n
>
x
≥
0
(
2
n
+
1
−
1
)
+
x
,
0
≥
x
>
−
2
n
(
m
o
d
(
2
n
+
1
−
)
)
[x]_反 = \begin{cases} 0,x,2^n > x \geq 0 \\ (2^{n+1} -1) + x,0 \geq x > -2^n (mod (2^{n+1} - )) \end{cases}
[x]反={0,x,2n>x≥0(2n+1−1)+x,0≥x>−2n(mod(2n+1−))
式中,x为真值,n为整数的位数。
比如
x = +1101, [ x ] 反 [x]_反 [x]反 = 0,1101
x = -1101, [ x ] 反 [x]_反 [x]反 = 1,0010
小数反码的定义:
[
x
]
反
=
{
x
,
1
>
x
≥
0
(
2
−
2
−
n
)
+
x
,
0
≥
x
>
1
)
[x]_反 = \begin{cases} x,1 > x \geq 0 \\ (2 - 2^{-n}) + x,0 \geq x >1) \end{cases}
[x]反={x,1>x≥0(2−2−n)+x,0≥x>1)
式中,x为真值,n为小数的位数。
比如
x = +0.0110, [ x ] 反 [x]_反 [x]反 = 0,0110
x = -0.0110, [ x ] 反 [x]_反 [x]反 = 1,1001
上述三种方式的数字编码方式特点如下:
1、最高位均为符号位
2、当真值为真时,三种编码的表示相同
3、当真值为负时,三种编码表示的符号位相同,都是“1”;而数值部分有以下关系,补码是原码的求反加一,反码是原码的每位求反。
移码表示法
补码可以用来做有符号数的加减运算,但是从数值上看,不能直观的看出来数值的大小,因此又创造出移码。
[
x
]
移
=
2
n
+
x
,
2
n
>
x
≥
−
2
n
)
[x]_移 = 2^n + x,2^n > x \geq -2^n)
[x]移=2n+x,2n>x≥−2n)
式中,x为真值,n为整数的位数。
在真值上加上一个偏移,得到的结果全部都大于0,这样就可以直观的比较数值的大小了。
数的定点和浮点表示
数的定点表示
小数点固定在某一位置的数为顶点数,有以下两种格式:
1、当小数点位于数符和第一位数值位之间时,表示为纯小数;
2、当小数点位于数值位之后时,机器内的数为纯整数。
小数的表示范围是: − ( 1 − 2 − n ) 到 ( 1 − 2 − n ) -(1-2^{-n})到(1-2^{-n}) −(1−2−n)到(1−2−n)
整数的表示范围是: − ( 2 n − 1 ) 到 ( 2 n − 1 ) -(2^{n}-1)到(2^{n}-1) −(2n−1)到(2n−1)
数的浮点表示
但是经常可能碰到数据的数值范围很大的数据,这如果用整数表示的话会难以想象。
比如电子的质量:
9
∗
1
0
−
28
g
9*10^{-28}g
9∗10−28g,太阳的质量:
2
∗
1
0
33
g
2*10^{33}g
2∗1033g。
通常,浮点数被表示成:
N
=
S
×
r
j
N = S × r^j
N=S×rj
S为尾数(可正可负,小数),j为阶码(可正可负,整数),r是基数(或基值,可以取2,4,8,16等)。
阶码的m位表示了浮点数的表示范围,尾数的n位反映了浮点数的精度。
浮点数的表示范围:
最大正数为: 0.111...1 × 2 + 111...1 0.111...1 ×2^{+111...1} 0.111...1×2+111...1,小数部分是 1 − 2 − n 1-2^{-n} 1−2−n,阶码部分是 ( 2 m − 1 ) (2^{m} - 1) (2m−1)
即 ( 1 − 2 − n ) × 2 ( 2 m − 1 ) (1-2^{-n}) × 2^{(2^{m} - 1)} (1−2−n)×2(2m−1)
最小正数为: 0.000...1 × 2 − 111...1 0.000...1 ×2^{-111...1} 0.000...1×2−111...1,小数部分 0.000...1 0.000...1 0.000...1,阶码部分是 − ( 2 m − 1 ) -(2^{m} - 1) −(2m−1)
即 2 − n × 2 − ( 2 m − 1 ) 2^{-n} × 2^{-(2^{m} - 1)} 2−n×2−(2m−1)
最大负数为: − 0.000...1 × 2 − 111...1 -0.000...1 ×2^{-111...1} −0.000...1×2−111...1,小数部分是 − 2 − n -2^{-n} −2−n,阶码部分是 − ( 2 m − 1 ) -(2^{m} - 1) −(2m−1)
即 ( − 2 − n ) × 2 − ( 2 m − 1 ) (-2^{-n}) × 2^{-(2^{m} - 1)} (−2−n)×2−(2m−1)
最小负数为: − 0.111...1 × 2 111...1 -0.111...1 ×2^{111...1} −0.111...1×2111...1,小数部分 0.111...1 0.111...1 0.111...1,阶码部分是 ( 2 m − 1 ) (2^{m} - 1) (2m−1)
即 − ( 1 − 2 − n ) × 2 ( 2 m − 1 ) -(1-2^{-n}) × 2^{(2^{m} - 1)} −(1−2−n)×2(2m−1)
浮点数的规格化
首先,一般规定浮点数的尾数用纯小数形式表示,比如 0.110101 × 2 10 0.110101 × 2^{10} 0.110101×210、 0.00110101 × 2 100 0.00110101 × 2^{100} 0.00110101×2100。
如果浮点数的尾数最高位为1,则将其称为规格化数,这种方式精度最高。
定点数和浮点数的比较
比较点 | 定点数 | 浮点数 |
---|---|---|
表示范围 | 数的位数相同时,表示范围比浮点小 | 数的位数相同时,表示范围比定点大 |
精度 | 精度比浮点低 | 规格化时,精度比定点高 |
运算速度及复杂度 | 较浮点数简单得多 | 运算步骤多,运算速度低,运算线路复杂 |
溢出判断 | 对数值本身进行判断 | 对阶码进行判断 |