Author: Once day date:2022年7月27日
漫漫长路才刚刚开始,不要甘于平凡。
每台计算机都有一个字长(word size),指明指针数据的标称大小(nominal size)。
其虚拟地址范围和字长的关系如下:
a
d
d
r
=
[
0
,
2
w
−
1
]
addr=[0,2^w-1]
addr=[0,2w−1]
字节顺序:
小端法:在内存中按照最低有效字节到最高有效字节的顺序存储对象。
大端法:按照最高有效字节到最低有效字节的顺序存储。
布尔代数的布尔环:(a^b)^a=b
左移位:没有歧义,左端舍弃,右端补0。
右移位:有两种,逻辑右移和算术右移。
以下是示例:
操作 | 参数x值[01100011] | 参数x值[10010101] |
---|---|---|
x << 4 | [00110000] | [01010000] |
x >> 4(逻辑右移) | [00000110] | [00001001] |
x >> 4(算术右移) | [00000110] | [11111001] |
c语言标准未定义有符号数使用右移的类型,但常见编译器使用算术右移。
当位移量很大时,一般遵守规则:移动位数k不超过数据的最大表示位数w,即k mod w.
对向量
x
⃗
=
[
x
w
−
1
,
x
w
−
2
,
.
.
.
,
x
0
]
\vec{x}=[x_{w-1},x_{w-2},...,x_0]
x=[xw−1,xw−2,...,x0]存在:
B
2
U
w
(
x
⃗
)
=
∑
i
=
0
w
−
1
x
i
2
i
B2U_w(\vec{x})=\sum^{w-1}_{i=0}x_i2^i
B2Uw(x)=i=0∑w−1xi2i
B
2
U
w
(
)
B2U_w()
B2Uw()函数将一个长度为w的0/1串映射到非负整数。
因此w位向量最大值为:
U
M
a
x
w
=
∑
i
=
0
w
−
1
2
i
=
2
w
−
1
UMax_w=\sum^{w-1}_{i=0}2^i=2^w-1
UMaxw=i=0∑w−12i=2w−1
无符号数的编码具有唯一性,即每个位于
[
0
,
2
w
−
1
]
[0,2^w-1]
[0,2w−1]之间的数都有唯一一个w为的值编码。
补码(two’s-complement):将最高有效位解释为负权(negative weight)。
对向量
x
⃗
=
[
x
w
−
1
,
x
w
−
2
,
.
.
.
,
x
0
]
\vec{x}=[x_{w-1},x_{w-2},...,x_0]
x=[xw−1,xw−2,...,x0]存在:
B
2
T
w
(
x
⃗
)
=
−
x
w
−
1
2
w
−
1
+
∑
i
=
0
w
−
2
x
i
2
i
B2T_w(\vec{x})=-x_{w-1}2^{w-1}+\sum^{w-2}_{i=0}x_i2^i
B2Tw(x)=−xw−12w−1+i=0∑w−2xi2i
最高有效位也成为了符号位。其极值为:
T
M
a
x
w
=
−
0
∗
2
w
−
1
+
∑
i
=
0
w
−
2
2
i
=
2
w
−
1
−
1
T
M
i
n
w
=
−
1
∗
2
w
−
1
+
∑
i
=
0
w
−
2
0
∗
2
i
=
−
2
w
−
1
TMax_w=-0*2^{w-1}+\sum^{w-2}_{i=0}2^i=2^{w-1}-1\\ TMin_w=-1*2^{w-1}+\sum^{w-2}_{i=0}0*2^i=-2^{w-1}
TMaxw=−0∗2w−1+i=0∑w−22i=2w−1−1TMinw=−1∗2w−1+i=0∑w−20∗2i=−2w−1
有符号数的编码同样具有唯一性!
反码(One’s Complement):最高有效位权重是
−
(
2
w
−
1
−
1
)
-(2^{w-1}-1)
−(2w−1−1)
B
2
O
w
(
x
⃗
)
=
−
x
w
−
1
(
2
w
−
1
−
1
)
+
∑
i
=
0
w
−
2
x
i
2
i
B2O_w(\vec{x})=-x_{w-1}(2^{w-1}-1)+\sum^{w-2}_{i=0}x_i2^i
B2Ow(x)=−xw−1(2w−1−1)+i=0∑w−2xi2i
原码(Sign-Magnitude):最高有效位是符号位,用确定正负号。
B
2
S
w
(
x
⃗
)
=
(
−
1
)
x
w
−
1
⋅
(
∑
i
=
0
w
−
2
x
i
2
i
)
B2S_w(\vec{x})=(-1)^{x_{w-1}}\cdot(\sum^{w-2}_{i=0}x_i2^i)
B2Sw(x)=(−1)xw−1⋅(i=0∑w−2xi2i)
这两种表示法都会产生一个问题,那就是0有两种表示方式。
强制转换的结果是保持位值不变,只是重新改变了解释这些位的方式。
补码转换为无符号数可表示为如下:
T
2
U
w
(
x
)
=
{
x
+
2
w
x
<
0
x
x
≥
0
T2U_w(x)=
显而易见,一个小负数,将被转化为很大的正数。
无符号数转换为补码:
U
2
T
w
(
u
)
=
{
u
x
≤
T
M
a
x
w
u
−
2
w
x
>
T
M
a
x
w
U2T_w(u)=
在c标准库文件里limits.h,INT_MIN = (-INT_MAX -1)=-2147483647-1。
这是一种很保守的表示方法。
无符号数的零扩展:
对w位向量 x ⃗ = [ x w − 1 , x w − 2 , . . . , x 0 ] \vec{x}=[x_{w-1},x_{w-2},...,x_0] x=[xw−1,xw−2,...,x0]扩展到w‘位向量 x ′ ⃗ = [ 0 , 0 , . . . , 0 , 0 , x w − 1 , x w − 2 , . . . , x 0 ] \vec{x'}=[0,0,...,0,0,x_{w-1},x_{w-2},...,x_0] x′=[0,0,...,0,0,xw−1,xw−2,...,x0]。
只需要在开头添加零即可。
符号数的符号扩展:
对w位向量 x ⃗ = [ x w − 1 , x w − 2 , . . . , x 0 ] \vec{x}=[x_{w-1},x_{w-2},...,x_0] x=[xw−1,xw−2,...,x0]扩展到w‘位向量 x ′ ⃗ = [ x w − 1 , . . . , x w − 1 , x w − 1 , x w − 2 , . . . , x 0 ] \vec{x'}=[x_{w-1},...,x_{w-1},x_{w-1},x_{w-2},...,x_0] x′=[xw−1,...,xw−1,xw−1,xw−2,...,x0]。
在表示中添加最高有效位,其值保持不变。
在C语言标准中:
如果将short值转换为unsigned int值,那么其转换顺序为:(unsigned int)(int) short_value。
截断一个数字时,会直接丢弃高位。
无符号数的截断:
对w位向量 x ⃗ = [ x w − 1 , x w − 2 , . . . , x 0 ] \vec{x}=[x_{w-1},x_{w-2},...,x_0] x=[xw−1,xw−2,...,x0]截断到k位向量 x ′ ⃗ = [ x k − 1 , x k − 2 , . . . , x 0 ] \vec{x'}=[x_{k-1},x_{k-2},...,x_0] x′=[xk−1,xk−2,...,x0]。
对于其值,则有 x ′ = x m o d 2 k x'=x \mod 2^k x′=xmod2k
补码有符号数截断:
对w位向量 x ⃗ = [ x w − 1 , x w − 2 , . . . , x 0 ] \vec{x}=[x_{w-1},x_{w-2},...,x_0] x=[xw−1,xw−2,...,x0]截断到k位向量 x ′ ⃗ = [ x k − 1 , x k − 2 , . . . , x 0 ] \vec{x'}=[x_{k-1},x_{k-2},...,x_0] x′=[xk−1,xk−2,...,x0]。
对于其值,则有 x ′ = U 2 T k ( x m o d 2 k ) x'=U2T_k(x\mod 2^k) x′=U2Tk(xmod2k)。
相当于重新解释最高位为符号位。
溢出的位直接丢弃:
0
≤
x
,
y
≤
2
w
x
+
y
=
{
x
+
y
x
+
y
<
2
w
x
+
y
−
2
w
2
w
≤
x
+
y
<
2
w
+
1
0\le x,y \le 2^w\\ x+y=
C程序不会将溢出作为错误而发信号。
可采用以下方法检测溢出:
模数加法形成了一种数学结构,成为阿贝尔群。
无符号求反,即加法逆元-x:
−
x
=
{
x
x
=
0
2
w
−
x
x
>
0
-x=
无符号乘法如下:
x
∗
y
=
(
x
∗
y
)
m
o
d
2
w
x*y=(x*y) \mod 2^w
x∗y=(x∗y)mod2w
两个数的w位补码之和与无符号数之和有完全相同的位级表示。
−
2
w
−
1
≤
x
,
y
≤
2
w
−
1
−
1
x
+
y
=
{
x
+
y
−
2
w
2
w
−
1
≤
x
+
y
x
+
y
−
2
w
−
1
≤
x
+
y
<
2
w
−
1
x
+
y
+
2
w
x
+
y
<
−
2
w
−
1
-2^{w-1}\le x,y \le 2^{w-1}-1\\ x+y=
检测补码加法中的溢出:
对满足 − 2 w − 1 ≤ x , y ≤ 2 w − 1 − 1 -2^{w-1}\le x,y \le 2^{w-1}-1 −2w−1≤x,y≤2w−1−1的x和y,令s=x+y,当且仅当x>0,y>0,但s≤0时,计算s发生了正溢出。
当且仅当x<0,y<0,但s≥0时,计算s发生了负溢出。
补码的一个奇特的规律:
T
M
i
n
w
+
T
M
i
n
w
=
−
2
w
−
1
+
(
−
2
w
−
1
)
=
0
TMin_w+TMin_w=-2^{w-1}+(-2^{w-1})=0
TMinw+TMinw=−2w−1+(−2w−1)=0
即补码非运算有:
−
x
=
{
T
M
i
n
w
x
=
T
M
i
n
w
−
x
x
>
T
M
i
n
w
-x=
在C语言中可以表达成:
-x = ~x + 1;
补码乘法如下:
x
∗
y
=
U
2
T
w
(
(
x
∗
y
)
m
o
d
2
w
)
x*y=U2T_w((x*y)\mod 2^w)
x∗y=U2Tw((x∗y)mod2w)
即将高于w位的乘积截断,再以有符号数的编码来解释位级含义。
无符号和补码乘法的低w位位级表示是相同的。推导省略…
可以使用移位运算来优化乘以2的幂次倍运算。
x
∗
2
k
=
x
<
<
k
x*2^k=x<
对于无符号数和补码数都成立。
可以使用移位运算来优化乘以2的幂次倍运算。
f
l
o
o
r
(
x
/
2
k
)
=
x
>
>
k
floor(x/2^k)=x>>k
floor(x/2k)=x>>k
对于无符号数和补码数都成立。
可以使用一点技巧来对补码数向上舍入:
c
e
i
l
(
x
/
2
k
)
=
(
x
+
(
1
<
<
k
)
−
1
)
>
>
k
ceil(x/2^k)=(x+(1<
二进制的小数位级形式如下的向量序列:
b
m
b
m
−
1
⋅
⋅
⋅
b
1
b
0
.
b
−
1
b
−
2
⋅
⋅
⋅
b
−
n
−
1
b
−
n
b_mb_{m-1}···b_1b_0.b_{-1}b_{-2}···b_{-n-1}b_{-n}
bmbm−1⋅⋅⋅b1b0.b−1b−2⋅⋅⋅b−n−1b−n
每个位表示0或1,再给每个数一个权重,则有:
b
=
∑
i
=
−
n
m
2
i
∗
b
i
b=\sum_{i=-n}^{m}2^i*b_i
b=i=−n∑m2i∗bi
这种定点表示法,很难有效的表示很大的数字。
IEEE浮点标准使用以下形式表达一个数:
V
=
(
−
1
)
s
∗
M
∗
2
E
V=(-1)^s*M*2^E
V=(−1)s∗M∗2E
将浮点数的位表示划分为三个字段,分别对这些值进行编码:
浮点数 | 符号s | 阶码k | 小数frac |
---|---|---|---|
单精度 | 1位 | 8位 | 23位 |
双精度 | 1位 | 11位 | 52位 |
根据阶码的值,被编码的值可以分成四类(单精度为例):
种类描述 | 符号s | 阶码k | 小数frac |
---|---|---|---|
规格化的值 | 0或1 | 0任意 | |
非规格化的值 | 0或1 | 00000000 | 任意 |
无穷大 | 0或1 | 11111111 | 全0 |
NaN(不是一个数) | 0或1 | 11111111 | 非0 |
规格化的值:
当exp的位模式既不全0,也不全为1时。阶码字段被解释为以偏置形式表示的有符号整数。
比如对于单精度浮点数,其阶码位有8位,那么取值在1-254之间,偏置为127,则实际指数可取值[-126,127]。对于双精度来说,偏置为1023,实际指数取值[-1022,1023]。
小数字段被解释为小数值f,其范围[ 0 , 1 ),二进制表示为 0. f n − 1 f n − 2 ⋅ ⋅ ⋅ f 2 f 1 f 0 0.f_{n-1}f_{n-2}···f_2f_1f_0 0.fn−1fn−2⋅⋅⋅f2f1f0。
尾数定义为M = 1 + f 。 也被称为隐含的以1开头的表示。即科学计数法表示。
非规格化的值:
当阶码域全为0时,所表示的数是非规格化形式的,其指数值是固定的 E = 1 − B i a s E=1-Bias E=1−Bias,对于单精度,其固定时-126,双精度固定为-1022。
尾数定义为M = f ,直接是小数字段的值,不包含隐含的开头的1。
特殊值:
即阶码全为1时,一个表示无穷值,另外一个表示Not a Number。
浮点数的值不是均匀分布的,在0附近比较稠密,向外密度逐渐降低。
浮点数的位级表达形式是有序排列的,如果按无符号数的编码形式来解释,那么有:
以下是非负浮点数的实例:
描述 | 阶码exp | 小数frac | 单精度 | 单精度 | 双精度 | 双精度 |
---|---|---|---|---|---|---|
0 | 全0 | 全0 | 0 | 0.0 | 0 | 0.0 |
最小非规格化数 | 全0 | 1 | 2 − 23 × 2 − 126 2^{-23} \times 2^{-126} 2−23×2−126 | 1.45 × 1 0 − 45 1.45\times 10^{-45} 1.45×10−45 | 2 − 52 × 2 − 1022 2^{-52}\times 2^{-1022} 2−52×2−1022 | 4.9 × 1 0 − 324 4.9\times 10^{-324} 4.9×10−324 |
最大非规格化数 | 全0 | 全1 | ( 1 − 2 − 23 ) × 2 − 126 (1-2^{-23})\times 2^{-126} (1−2−23)×2−126 | 1.2 × 1 0 − 38 1.2\times 10^{-38} 1.2×10−38 | ( 1 − 2 − 52 ) × 2 − 1022 (1-2^{-52})\times 2^{-1022} (1−2−52)×2−1022 | 2.2 × 1 0 − 308 2.2\times 10^{-308} 2.2×10−308 |
最小规格化值 | 1 | 0 | 1 × 2 − 126 1\times 2^{-126} 1×2−126 | 1.2 × 1 0 − 38 1.2 \times 10^{-38} 1.2×10−38 | 1 × 2 − 1022 1\times 2^{-1022} 1×2−1022 | 2.2 × 1 0 − 308 2.2\times 10^{-308} 2.2×10−308 |
1 | 127 | 0 | 1 × 2 0 1\times 2^0 1×20 | 1.0 | 1 × 2 0 1\times 2^0 1×20 | 1.0 |
最大规格化值 | 254 | 全1 | ( 2 − 2 − 23 ) × 2 127 (2-2^{-23})\times 2^{127} (2−2−23)×2127 | 3.4 × 1 0 38 3.4\times 10^{38} 3.4×1038 | ( 2 − 2 − 52 ) × 2 1023 (2-2^{-52})\times 2^{1023} (2−2−52)×21023 | 1.8 × 1 0 308 1.8\times 10^{308} 1.8×10308 |
以下是一个实例,把整数值转变成IEEE单精度浮点数:
(IEEE单精度浮点数)([0][100011000][1000001110010000000000])=12345.0
这种摄入方式在非中间数时按四舍五入方法来取近似,但遇见中间数。
则其按舍入之后最低位为偶数的规则来进行近似!
如1.35近似为1.4,1.45近似为1.4。
这种近似方法可有效避免近似造成的统计性偏差。
必须是两个可能值的中间值才能采取这种策略。
因此,浮点数加法运算不具备结合性,乘法运算不具备交换性。
此外 ,浮点数乘法具有单调性:
对于任意的a,b,c,且它们都不为NaN,则有:
a
≥
b
且
c
≥
0
,
则有
a
∗
c
≥
b
∗
c
a
≥
b
且
c
≤
0
,
则有
a
∗
c
≤
b
∗
c
a\ge b 且c\ge 0 ,则有a*c\ge b*c \\ a\ge b 且c\le 0 ,则有a*c\le b*c
a≥b且c≥0,则有a∗c≥b∗ca≥b且c≤0,则有a∗c≤b∗c
从浮点数向整数转换可以能会溢出,精度也可能丢失。
当范围溢出时,Interl兼容处理器会有一个TMin值作为整数不确定值。
此外,Inter兼容处理器上也有一个“扩展精度”浮点形式,具有80位长,1个符号位,15个阶码位,1个整数位,63个小数位。
而且后来也出现了16位浮点数的IEEE标准。
(------------------完--------------------)
夜很深,但相信很多人依旧在奋斗,致敬每一个为了梦想不懈学习的人,期待日后有缘相见。