计算机的算术表示
整数表示
无符号数
计算机中的数字都由0与1表示,给定一串01序列,将其转换为无符号数的十进制
记序列为
X
n
−
1
X
n
−
1
X
n
−
2
X
.
.
.
X
0
X_{n-1}X_{n-1}X_{n-2}X_{...}X_0
Xn−1Xn−1Xn−2X...X0
其中
X
i
X_i
Xi的取值为0或1,则其对应的十进制值是
U
n
s
i
g
n
e
d
V
a
l
u
e
=
∑
k
=
0
n
−
1
X
k
∗
2
k
UnsignedValue = \sum_{k=0}^{n-1}X_k*2^k
UnsignedValue=k=0∑n−1Xk∗2k
无符号数的最大值(记为U
m
i
n
)
{min})
min)与最小值(记为
U
m
a
x
U_{max}
Umax)为:
U
m
i
n
=
0
⟺
X
k
=
0
k
=
0
,
1
,
2...
U_{min} = 0 \iff X_k = 0 \\ k = 0, 1, 2 ...
Umin=0⟺Xk=0k=0,1,2...
U m a x = ∑ k = 0 n − 1 2 k = 2 n − 1 ⟺ X k = 1 k = 0 , 1 , 2... U_{max} = \sum_{k = 0}^{n-1}2^k = 2^n - 1 \iff X_k = 1 \\ k = 0, 1, 2 ... Umax=k=0∑n−12k=2n−1⟺Xk=1k=0,1,2...
有符号数
有符号数可以带正负号,最高位为符号位,1为负,0为正。无符号有两种典型的表示方法,第一种是补码,第二种是原码。当今机器上的有符号数全部用补码表示,但是由于补码不是很好理解,所以往往也会用原码充当中间层:补码转为原码,再用原码来理解。
此处只给出将无符号的01序列转为对应的十进制值公式:
S
i
g
n
e
d
V
a
l
u
e
=
(
−
1
)
∗
2
n
−
1
∗
X
n
−
1
+
∑
k
=
0
n
−
2
X
k
∗
2
k
SignedValue = (-1)*2^{n-1}*X_{n-1}+\sum_{k=0}^{n-2}X_k*2^k
SignedValue=(−1)∗2n−1∗Xn−1+k=0∑n−2Xk∗2k
此公式表明:对于负数来说,最高位是符号位为1,其他位越小,则该负数越小,当其他位为0时,值最小,为
−
2
n
−
1
-2^{n-1}
−2n−1.同样,对于正数来说,当
X
n
−
1
X_{n-1}
Xn−1为0,也就是符号位为0,其他位全1时最大。
补码表示的最小值
T
m
i
n
T_{min}
Tmin与最大值$T_{max}为
T
m
i
n
=
−
2
n
−
1
T
m
a
x
=
∑
k
=
0
n
−
2
2
k
=
2
n
−
1
−
1
T_{min} = -2^{n-1}\\ T_{max} = \sum_{k = 0}^{n - 2}2^k = 2^{n-1} - 1
Tmin=−2n−1Tmax=k=0∑n−22k=2n−1−1
可以观察到补码的最小值比最大值的相反数还要小一,所以
T
m
i
n
T_{min}
Tmin常作为测试数据验证一些程序
有符号数性质公式
最小值等于最大值的相反数减一
T m i n = − T m a x − 1 T_{min} = -T_{max}-1 Tmin=−Tmax−1
负数的重复的前导一可以删去
比如二进制位 1111111111000000 , 前面重复了10个1, 这些重复的1可以删去只留下一个,也就是说 1111111111000000 = 1000000
对于二进制数
X
n
−
1
X
n
−
1
X
.
.
.
X
0
i
f
X
k
=
1
(
k
=
i
,
i
+
1
,
.
.
.
,
n
−
1
)
t
h
e
n
X
n
−
1
X
n
−
1
X
.
.
.
X
0
=
X
i
X
i
−
1
X
.
.
.
X
0
对于二进制数X_{n-1}X_{n-1}X{...}X_{0} \ \ \ \ \ \ \ \ \\ if\ \ X_{k} = 1 \ \ \ (k = i, i+1, ...,n-1)\\ then\ \ X_{n-1}X_{n-1}X{...}X_{0} = X_{i}X_{i-1}X{...}X_{0}
对于二进制数Xn−1Xn−1X...X0 if Xk=1 (k=i,i+1,...,n−1)then Xn−1Xn−1X...X0=XiXi−1X...X0
证明
X
n
−
1
X
n
−
1
X
.
.
.
X
0
=
(
−
1
)
∗
2
n
−
1
+
∑
k
=
0
i
−
1
X
k
∗
2
k
+
∑
k
=
i
n
−
2
2
k
=
∑
k
=
0
i
−
1
X
k
∗
2
k
+
(
(
−
1
)
∗
2
n
−
1
+
∑
k
=
i
n
−
2
2
k
)
=
∑
k
=
0
i
−
1
X
k
∗
2
k
+
(
−
1
)
∗
2
i
=
X
i
X
i
−
1
X
.
.
.
X
0
\begin{split} X_{n-1}X_{n-1}X{...}X_{0} \\ &= (-1)*2^{n-1}+\sum_{k=0}^{i-1}X_k*2^k + \sum_{k = i}^{n - 2}2^k \\ &= \sum_{k=0}^{i-1}X_k*2^k + ((-1)*2^{n-1}+\sum_{k = i}^{n - 2}2^k)\\ &= \sum_{k=0}^{i-1}X_k*2^k + (-1)*2^i \\ &= X_{i}X_{i-1}X{...}X_{0} \end{split}
Xn−1Xn−1X...X0=(−1)∗2n−1+k=0∑i−1Xk∗2k+k=i∑n−22k=k=0∑i−1Xk∗2k+((−1)∗2n−1+k=i∑n−22k)=k=0∑i−1Xk∗2k+(−1)∗2i=XiXi−1X...X0
得证
一个数的相反数等于其反码+1
证明:
X
n
−
1
X
n
−
1
X
.
.
.
X
0
=
(
−
1
)
∗
2
n
−
1
∗
X
n
−
1
+
∑
k
=
0
n
−
2
X
k
∗
2
k
X
n
−
1
‾
X
n
−
1
‾
X
.
.
.
‾
X
0
‾
=
(
−
1
)
∗
2
n
−
1
∗
(
1
−
X
n
−
1
)
+
∑
k
=
0
n
−
2
(
1
−
X
k
)
∗
2
k
=
−
2
n
−
1
+
∑
k
=
1
n
−
2
2
k
+
(
−
1
)
∗
[
(
−
1
)
∗
2
n
−
1
∗
X
n
−
1
+
∑
k
=
0
n
−
2
X
k
∗
2
k
]
=
−
1
−
X
n
−
1
X
n
−
1
X
.
.
.
X
0
\begin{split} X_{n-1}X_{n-1}X{...}X_{0} &= (-1)*2^{n-1}*X_{n-1}+\sum_{k=0}^{n-2}X_k*2^k \\ \overline{X_{n-1}}\ \overline{X_{n-1}}\ \overline{X{...}}\ \overline{X_{0}} &= (-1)*2^{n-1}*(1-X_{n-1})+\sum_{k = 0}^{n-2}(1-X_k)*2^k \\ &= -2^{n-1}+\sum_{k = 1}^{n-2}2^k + (-1)*[(-1)*2^{n-1}*X_{n-1}+\sum_{k=0}^{n-2}X_k*2^k] \\ &= -1 - X_{n-1}X_{n-1}X{...}X_{0} \end{split}
Xn−1Xn−1X...X0Xn−1 Xn−1 X... X0=(−1)∗2n−1∗Xn−1+k=0∑n−2Xk∗2k=(−1)∗2n−1∗(1−Xn−1)+k=0∑n−2(1−Xk)∗2k=−2n−1+k=1∑n−22k+(−1)∗[(−1)∗2n−1∗Xn−1+k=0∑n−2Xk∗2k]=−1−Xn−1Xn−1X...X0
因此
−
X
n
−
1
X
n
−
1
X
.
.
.
X
0
=
X
n
−
1
‾
X
n
−
1
‾
X
.
.
.
‾
X
0
‾
+
1
得证
因此 - X_{n-1}X_{n-1}X{...}X_{0} = \overline{X_{n-1}}\ \overline{X_{n-1}}\ \overline{X{...}}\ \overline{X_{0}}+1得证
因此−Xn−1Xn−1X...X0=Xn−1 Xn−1 X... X0+1得证
得证
有符号数与无符号数之间的转换
常见转换方式
B2U:B指的是binary二进制,2在英文中常指的是to,U指的是unsigned 无符号数,所以这个术语的意思是将二进制转换为一个无符号数,本质上是一个映射,用函数来理解的话就是,传进去一个二进制参数,经过B2U这个函数(映射),返回值是一个无符号数。显然,B2U的本质就是上面的公式
B
2
U
(
X
n
−
1
X
n
−
1
X
n
−
2
X
.
.
.
X
0
)
=
∑
k
=
0
n
−
1
X
k
∗
2
k
B2U(X_{n-1}X_{n-1}X_{n-2}X_{...}X_0) = \sum_{k=0}^{n-1}X_k*2^k
B2U(Xn−1Xn−1Xn−2X...X0)=k=0∑n−1Xk∗2k
注意:这里需要把
∑
k
=
0
n
−
1
X
k
∗
2
k
\sum_{k=0}^{n-1}X_k*2^k
∑k=0n−1Xk∗2k当成一个数来看待
B2T: T常指有符号数,所以,B2T如下所示
B
2
T
(
X
n
−
1
X
n
−
1
X
n
−
2
X
.
.
.
X
0
)
=
(
−
1
)
∗
2
n
−
1
∗
X
n
−
1
+
∑
k
=
0
n
−
2
X
k
∗
2
k
B2T(X_{n-1}X_{n-1}X_{n-2}X_{...}X_0) = (-1)*2^{n-1}*X_{n-1}+\sum_{k=0}^{n-2}X_k*2^k
B2T(Xn−1Xn−1Xn−2X...X0)=(−1)∗2n−1∗Xn−1+k=0∑n−2Xk∗2k
U2T: 给定一个无符号数,通过T2U映射以后,返回一个有符号数。可以利用复合函数的知识,利用上面两个B2U和B2T映射来推导这个映射
尝试用逆映射推导:
U
2
T
=
B
2
T
(
U
2
B
)
=
(
B
2
T
)
(
B
2
U
)
−
1
但是不好求逆映射
第二种方法:
B
2
U
−
B
2
T
=
X
n
−
1
∗
2
n
−
1
+
2
n
−
1
∗
x
n
−
1
=
X
n
∗
2
n
所以
B
2
T
=
B
2
U
−
X
n
∗
2
n
此处的
B
2
U
代指的是
B
(
X
n
−
1
X
n
−
1
X
.
.
.
X
0
)所对应的无符号数,
B
2
T
代指的是
B
(
X
n
−
1
X
n
−
1
X
.
.
.
X
0
)所对应的有符号数
所以
U
2
T
(
u
0
)
=
t
0
=
u
0
−
X
n
∗
2
n
尝试用逆映射推导:U2T = B2T(U2B) = (B2T)(B2U)^{-1}但是不好求逆映射 \\ 第二种方法:B2U - B2T = X_{n-1}*2^{n-1}+2^{n-1}*x_{n-1} = X_{n}*2^{n} \\ 所以 B2T = B2U - X_{n}*2^{n} \\ 此处的B2U代指的是B(X_{n-1}X_{n-1}X{...}X_{0})所对应的无符号数,\\ B2T代指的是B(X_{n-1}X_{n-1}X{...}X_{0})所对应的有符号数 \\ 所以 U2T(u_{0})= t_{0} = u_{0} - X_{n}*2^{n}
尝试用逆映射推导:U2T=B2T(U2B)=(B2T)(B2U)−1但是不好求逆映射第二种方法:B2U−B2T=Xn−1∗2n−1+2n−1∗xn−1=Xn∗2n所以B2T=B2U−Xn∗2n此处的B2U代指的是B(Xn−1Xn−1X...X0)所对应的无符号数,B2T代指的是B(Xn−1Xn−1X...X0)所对应的有符号数所以U2T(u0)=t0=u0−Xn∗2n
上面的推导利用了 U 与 T 具有相同的二进制表示(B)
理解,对于正数来说, X n X_{n} Xn为0,则 t 0 = u 0 t_{0} = u_0 t0=u0,也就是正数的无符号数与有符号数是相同的
对于负数来说,有符号数等于无符号数减去
t 0 = { u 0 , u 0 < = T m a x u 0 − 2 n , u 0 > T m a x 或等价的 u 0 > = 2 n − 1 t_{0} =\begin{cases} u_{0} , & u_{0} <= T_{max} \\ u_{0} - 2^n, & u_{0} > T_{max} 或等价的 u_{0} >= 2^{n-1} \end{cases} t0={u0,u0−2n,u0<=Tmaxu0>Tmax或等价的u0>=2n−1
T2U : T2U 其实就是U2T的逆过程,稍微移项即可得到。下面图像的单向箭头用双向箭头其实更为贴切,这是一个双射。
u
0
=
{
t
0
,
t
0
>
0
t
0
+
2
n
,
t
0
<
0
u_{0} = \begin{cases} t_{0} ,&t_{0} > 0 \\ t_{0}+2^n, &t_{0} < 0 \end{cases}
u0={t0,t0+2n,t0>0t0<0
下面的一张图片非常便于记忆 (原创图片,简单了点,求大神完善🐶)
核心归纳:无符号与有符号的差是 2 n 2^{n} 2n, 需要 减去 2 n 2^{n} 2n的临界值是 2 n − 1 2^{n-1} 2n−1时,不是 2 n − 1 − 1 2^{n-1} - 1 2n−1−1
浮点数表示
背景介绍:现今世界上的绝大多数机器运行的浮点数都是采用了IEEE754标准,这个标准规定了浮点数如何进行编码,这个标准是由UCB(加州伯克利,四大CS神校之一,🏫)的教授指定。
浮点数的组成
浮点数采用科学计数法的思想,将一个带有小数的浮点数先进行移位,比如 234.53移位为 2.3453 ∗ 1 0 2 2.3453*10^2 2.3453∗102,只保留一位个位数,当然,对于二进制而言,-10011.101移位为 -1.0011101* 2 4 2^4 24,所以一个浮点数被分成三部分,分别是符号位,阶码(2的幂数,比如上面的4),尾数(上面的1.0011101),分别用S, E, F来表示,所以核心任务便是如何用二进制串来存储S, E, F.
容易想到,将二进制的最高位设置为符号位,紧随其后的几位设置为E的补码,最后的几位设置为F的补码,但是采用这种方式编码的效果不好,精度低,不够巧妙。所以接下来就引入IEEE754标准的编码方式。
后续中统一对S的编码用s (sign)表示,对E的编码用e (exp)表示,对F的编码用f (frac)表示
浮点数
V
a
l
u
e
=
(
−
1
)
S
∗
F
∗
2
E
浮点数Value = (-1)^S*F*2^E
浮点数Value=(−1)S∗F∗2E
下面是对 float 和 double 的编码组成表示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HqaorrUr-1664542987155)(F:\笔记\体系结构\1_tu8UHXww5mM6ndUVNA_dAg.png)]
由于float和double的原理都是一模一样的,所以只对float进行介绍,double完全一样。
规格化与非规格化
IEEE754标准中浮点数分为4种,分别为非规格化、规格化、无穷大、NaN(not a number), 根据 e 和 f的值来进行区分的。下面这张图必须背下来,必考
规格化的数
s 决定了符号,1为负,0为正, S = s;
为了计算E,需要引入一个叫bias(偏差)的概念, IEEE754中,因为s表示符号位,而E的正负是与s无关的,为了表示E的正负, 使用E = B2U(e) - bias 来表示E的值,对于规格化的数来说,
b
i
a
s
=
2
n
−
1
−
1
bias = 2^{n-1}-1
bias=2n−1−1
其中n为阶码(e)的总位数,比如float 为8
简记为 E = e - bias
非规格化的数字的另一个特点就是所有数开头都有一个隐含的一,啥意思呢?看例子
0.01101 = 1.101 *
2
2
2^{2}
22
110.1001 = 1.101001 *
2
−
2
2^{-2}
2−2
对于规格化的数,一定是将其化为1.***的形式,其中***就是F,小数部分,也是我们要编码的对象,所以对于所有规格化的数字都有这个前导的1,因此,这个前导的1就可以不用再编码,只要是规格化的数字都默认加上即可。
小数部分的编码:
F
=
B
2
U
(
f
)
+
1
F = B2U(f) + 1
F=B2U(f)+1
其中f 是二进制编码串,通过B2U的映射变为无符号数即可,注意,因为这是小数部分,所以乘的应该是
2
−
1
2^{-1}
2−1
X
n
−
1
X
n
−
1
X
n
−
2
X
.
.
.
X
0
=
∑
k
=
0
n
−
1
X
k
∗
2
−
k
X_{n-1}X_{n-1}X_{n-2}X_{...}X_0 = \sum_{k=0}^{n-1}X_k*2^{-k}
Xn−1Xn−1Xn−2X...X0=k=0∑n−1Xk∗2−k
理解这一点的关键是理解二进制串前面还有一个隐含的小数点。
规格化对应实数中不是特别小也不是特别大的数字
非规格化的数字
S = s ; E = 1 − b i a s ; b i a s = 2 k − 1 − 1 ; F = B 2 U ( f ) S = s; \\ E = 1 - bias; \\ bias = 2^{k-1} - 1; \\ F = B2U(f) S=s;E=1−bias;bias=2k−1−1;F=B2U(f)
- 和规格化的数相比,它的E发生了变化,变为了 1- bias 而不是 e -bias (0 - bias );
2. 其次,F没有开头隐含的1了。
这两个变化是为了在最小的规格化数与最大的非规格化数之间形成一种平滑的过渡。为了更深入的理解这一点,有兴趣的可以自己算一下最小的规格化数和最大的非规格化数。
非规格化对应特别小,特别接近0的数字
无穷大和NaN
当s 为0 ,为正无穷, s 为1, 为负无穷。NaN 能够认出来即可
总结
一表胜千言
类型 | S | e | E | bias | F |
---|---|---|---|---|---|
规格化 | s | e不全为0 | e - bias, | 2 n − 1 − 1 2^{n-1}-1 2n−1−1 | 1 + f |
非规格化 | s | e全为0 | 1 - bias, e全为0 | 2 n − 1 − 1 2^{n-1}-1 2n−1−1 | f |
无穷大 | s | e全1 | f全为0 | ||
NaN | s | e全1 | f不全为0 |
浮点数 V a l u e = ( − 1 ) S ∗ F ∗ 2 E 浮点数Value = (-1)^S*F*2^E 浮点数Value=(−1)S∗F∗2E