文章目录
整数表示
整数编码
无符号数
相当于只有正数,用U来表达
二进制位模式转换为无符号数:
B 2 U ( X ) = ∑ i = 0 w − 1 x i ⋅ 2 i B 2 U(X)=\sum_{i=0}^{w-1} x_{i} \cdot 2^{i} B2U(X)=∑i=0w−1xi⋅2i
即按照权值将二进制数转换为十进制数
无符号数转换为二进制位模式:
U2Bw(x) = Bw(x),即将x由当前进制转换为二进制位模式,如U2B4(12)=1100。
有符号数
若符号位为0则表示正数,数值等于位模式表示的数;若符号位为1则表示负数,数值为-2w-1+剩下的位模式表示的数值。
二进制位模式转换为有符号数:
B 2 T ( X ) = − x w − 1 ⋅ 2 w − 1 + ∑ i = 0 w − 2 x i ⋅ 2 i B 2 T(X)=-x_{w-1} \cdot 2^{w-1}+\sum_{i=0}^{w-2} x_{i} \cdot 2^{i} B2T(X)=−xw−1⋅2w−1+∑i=0w−2xi⋅2i
有符号数转换为二进制位模式:
法一:
T
2
B
w
(
x
)
=
{
U
2
B
(
x
)
,
x
w
−
1
=
0
,
当
符
号
位
为
0
"
1
"
+
B
w
(
x
−
(
−
2
w
−
1
)
)
,
当
符
号
位
为
1
T2B_w(x)= \begin{cases} U 2 B(x), x_{w-1}=0,当符号位为0\\ "1"+B_w(x-(-2^{w-1})),当符号位为1\\ \end{cases}
T2Bw(x)={U2B(x),xw−1=0,当符号位为0"1"+Bw(x−(−2w−1)),当符号位为1
其中x-(-2w-1)代表x到-2w-1的距离,从下图也可以看出,有符号数(补码数)的负数的大小是使用它到-2w-1的距离进行衡量的。
例如求-12和-16的补码(w=5):
-2w-1=-24=-16
-12差4,4=>0b100
故-12=>0b10100
-16差0,
故-16=>0b10000
法二:
T
2
B
w
(
x
)
=
{
U
2
B
(
x
)
,
x
w
−
1
=
0
,
当
符
号
位
为
0
!
T
2
B
w
(
−
x
)
+
1
,
当
符
号
位
为
1
且
x
!
=
−
2
w
−
1
"
1
"
+
"
0
"
∗
(
w
−
1
)
,
当
x
=
−
2
w
−
1
T2B_w(x)= \begin{cases} U 2 B(x), x_{w-1}=0,当符号位为0\\ ! T2B_w(-x)+1, 当符号位为1且x!=-2^{w-1}\\ "1"+"0"*(w-1),当x=-2^{w-1} \end{cases}
T2Bw(x)=⎩⎪⎨⎪⎧U2B(x),xw−1=0,当符号位为0!T2Bw(−x)+1,当符号位为1且x!=−2w−1"1"+"0"∗(w−1),当x=−2w−1
即当x为负数时,可以先求它相反数(为正数)的位模式,然后对它相反数的位模式的尾数(即去掉符号位)进行取反加一,这样就能得到-x到2w-1的距离,也就是x到-2w-1的距离,然后符号位取“1”即可得到对应的有符号数(补码数),所以这个时候相当于带符号位也一起取反了,所以我们可以对整个二进制位模式进行取反+1直接获得相反数的二进制位模式。但这个情况有例外,即当x=-2w-1,若对其取相反数,比如x=-16,w=5,则-x=16,这个时候16无法用二进制表示出来,所以这种情况下我们直接采用 “1”+“0” * (w-1)的方式,即-16=>0b10000。
例子-4,-7和-8,w=4:
-(-4)=4=>0b0100
~0b0100+1=0b1011+1=0b1100
-(-7)=7=>0b0111
~0b0111+1=0b1000+1=0b1001
-8=-24-1
所以-8=>0b1000
使用这两种方法都可以将x转换为有符号数的二进制位模式,本质上当x为负数时都是求它到-2w-1的距离。
有符号数和无符号数的转换
两者的转换(例如在C语言中),在计算机中都是先将原表示形式转换为二进制位模式,再进一步使用二进制位模式转换为对应的目标形式的,即:
先考虑T2Uw(有符号数转换为无符号数):
B2Uw(x) −B2Tw(x) = xw−1(2w−1−−2w−1) = xw-12w
即相同的二进制位模式分别转换为两种数时,有符号数和无符号数的差距为xw-12w。
B2Uw(x) = xw-12w + B2Tw(x)
即:
B 2 U w ( T 2 B w ( x ) ) = T 2 U w ( x ) = x w − 1 2 w + x B 2 U_{w}\left(T 2 B_{w}(x)\right)=T 2 U_{w}(x)=x_{w-1} 2^{w}+x B2Uw(T2Bw(x))=T2Uw(x)=xw−12w+x
也可以表示成:
T
2
U
w
(
x
)
=
{
x
,
当
x
w
−
1
=
0
,
即
x
为
正
数
2
w
+
x
,
当
x
w
−
1
=
1
,
即
x
为
负
数
T2U_w(x)= \begin{cases} x,~~~~~~~当x_{w-1}=0,即x为正数\\ 2^w+x, 当x_{w-1}=1,即x为负数 \end{cases}
T2Uw(x)={x, 当xw−1=0,即x为正数2w+x,当xw−1=1,即x为负数
由下图也可以看出,相同的二进制位模式表示的两种数(xw-1=1),
它们相差了2 * 2w-1=2w
有符号数到无符号数的映射图:
考虑U2Tw(无符号数转换为有符号数):
思路基本类似:
B2Tw(x) − B2Uw(x) = xw-1(−2w−1−2w−1) = -xw−12w
B2Tw(x) = B2Uw(x) - xw−12w
即:
B
2
T
w
(
U
2
B
w
(
u
)
)
=
U
2
T
w
(
u
)
=
−
u
w
−
1
2
w
+
u
B 2 T_{w}\left(U 2 B_{w}(u)\right)=U 2 T_{w}(u)=-u_{w-1} 2^{w}+u
B2Tw(U2Bw(u))=U2Tw(u)=−uw−12w+u
可以写成:
U
2
T
w
(
u
)
=
{
u
,
u
<
2
w
−
1
u
−
2
w
,
u
≥
2
w
−
1
U 2 T_{w}(u)=\left\{\begin{array}{cl}u, & u<2^{w-1} \\ u-2^{w}, & u \geq 2^{w-1}\end{array}\right.
U2Tw(u)={u,u−2w,u<2w−1u≥2w−1
无符号数到有符号数的映射图:
C语言程序中的整数
- 无符号数:unsigned int ( short / long)
- 带符号整数: int ( short / long)
- C语言中的数字12388等,都是表示有符号数(即默认是有符号数)
- 而无符号数使用12388u或12388U
转换时机:
- 显式转换(强制)
- 隐式转换(不同类型变量间赋值)
- printf输出时完全依赖于格式字符串,而与变量/数字本身的类型无关
两种类型数在C语言中的比较
当有符号数和无符号数进行比较时,C语言的处理是先将有符号数转换为无符号数(即使用相同的二进制位模式映射到无符号数),然后再进行比较。
例题:
当两个比较数的类型相同时直接比较大小
当两比较熟类型不相同时,相当于直接比较它们的二进制位模式的大小。
扩展与截断
扩展
从 w-bit 扩展到w+k-bit(数值不变)
- 零扩展
- 将高k位置为0
- 符号扩展(有符号数):
- 将符号为在高位重复 k次
既变大小又变类型——C语言规则要求:先转换为32位再进行类型转换
short sx = -12345;
unsigned uy = sx;
例如这个例子,先将sx的16位扩展到32位,然后再按位模式映射到无符号数存储到变量uy中。
截断
无论是有符号数还是无符号数,截断的过程都是将二进制位模式截断后再映射到对应的表示。
整数运算
整数加法
无符号整数加法
- 操作数范围:0 ≤ x, y ≤ 2w − 1
- 和的范围(需要w+1位):0 ≤ x + y ≤ 2w+1 − 2
- 可表示范围:0 ≤ res ≤ 2w − 1
x + w u y = { x + y , x + y < 2 w x + y − 2 w , 2 w ≤ x + y < 2 w + 1 , 溢 出 ( 第 w 位 丢 弃 ) x+_{w}^{\mathrm{u}} y=\left\{\begin{array}{ll}x+y, & x+y<2^{w} \\ x+y-2^{w}, & 2^{w} \leq x+y<2^{w+1} ,溢出(第w位丢弃)\end{array}\right. x+wuy={x+y,x+y−2w,x+y<2w2w≤x+y<2w+1,溢出(第w位丢弃)
有符号整数(补码)加法
- 操作数范围:−2w−1 ≤ x, y ≤ 2w−1 − 1
- 和的范围:− 2w ≤ x + y ≤ 2w − 2
- 可表示范围: −2w−1 ≤ x, y ≤ 2w−1 − 1
x + w t y = { x + y − 2 w , 2 w − 1 ≤ x + y Positive overflow x + y , − 2 w − 1 ≤ x + y < 2 w − 1 Normal x + y + 2 w , x + y < − 2 w − 1 Negative overflow x+_{w}^{\mathrm{t}} y=\left\{\begin{array}{ll}x+y-2^{w}, & 2^{w-1} \leq x+y \quad \text { Positive overflow } \\ x+y, & -2^{w-1} \leq x+y<2^{w-1} \quad \text { Normal } \\ x+y+2^{w}, & x+y<-2^{w-1} \quad \text { Negative overflow }\end{array}\right. x+wty=⎩⎨⎧x+y−2w,x+y,x+y+2w,2w−1≤x+y Positive overflow −2w−1≤x+y<2w−1 Normal x+y<−2w−1 Negative overflow
结果映射图:
例子:
符号位发生改变即发生了溢出。
正溢:符号位由0变为1,x=>x-2w
负溢:符号位由1变为0,x=>x+2w
整数乘法
无符号整数乘法
- 操作数范围:0 ≤ x, y ≤ 2w−1
- 乘积的范围(2w位):0 ~ (2w − 1)2=22w − 2w+1 + 1
- 可表示范围w位
x ∗ w u y = ( x ⋅ y ) m o d 2 w x * \ _{w}^{\mathrm{u}} y=(x \cdot y) \bmod 2^{w} x∗ wuy=(x⋅y)mod2w
即超出部分直接截断处理。
补码乘法
x ∗ w t y = U 2 T w ( ( x ⋅ y ) m o d 2 w ) x *\ _{w}^{\mathrm{t}} y=U 2 T_{w}\left((x \cdot y) \bmod 2^{w}\right) x∗ wty=U2Tw((x⋅y)mod2w)
无论是有符号数还是无符号数的运算,都可以视为先直接运算得到结果,再将结果的二进制位模式进行截断处理得到最终的二进制位模式再映射到对应的数值,如以下例子所示:
浮点数
二进制小数
IEEE 754标准
单精度和多精度浮点数:
以阶码区分的4种状态:
阶码E的运算:
E
=
{
1
−
(
2
w
−
1
−
1
)
=
−
2
w
−
1
+
2
e
−
(
2
w
−
1
−
1
)
E= \begin{cases} 1-(2^{w-1}-1)=-2^{w-1}+2\\ e-(2^{w-1}-1) \end{cases}
E={1−(2w−1−1)=−2w−1+2e−(2w−1−1)
从图中也可以看出,尾数每增加1,数值增加为2E * 2w,其中w是尾数位数。
例如0b0 0111 000和0b0 0111 001相差1/8,此时E=0,w=3,2E * 2w=1/8。
小数的舍入
C语言中的浮点数
- 两种浮点数类型:float 和double
- C99包含第三种浮点数类型:long double
- 整数和浮点数转换规则:
- int转换为float,不会溢出,可能被舍入(int32位,float 的尾数只有23位)
- int或float转换为double,能够准确表示(double52位)
- double转换为float,可能会溢出+∞或- ∞,也可能会舍入
- float或double转换为int,可能会溢出,如果需要舍入则是向零舍入