原码反码补码
**原码:**一个数的原码(原始的二进制码)有如下特点:
- 最高位做为符号位,0表示正,为1表示负
- 其它数值部分就是数值本身绝对值的二进制数
- 负数的原码是在其绝对值的基础上,最高位变为1
**反码:**对于正数,反码与原码相同;对于负数,符号位不变,其它部分取反(1变0,0变1)
注:反码运算也不方便,通常用来作为求补码的中间过渡。
补码:
在计算机系统中,数值一律用补码来存储。
补码特点:
- 对于正数,原码、反码、补码相同
- 对于负数,其补码为它的反码加1
- 符号位不动,源码其他位求反,最后整个数加1,得到补码
无符号数编码
对向量$\vec{x}=[ x_{w-1},x_{w-1}, . . . ,x_{1},x_{0}] $无符号编码使用的是原码进行编码
B
2
U
ω
(
x
⃗
)
=
∑
i
=
0
w
−
1
x
i
2
i
B2U_ω(\vec{x})=\sum_{i=0}^{w-1}x_i2^i
B2Uω(x)=i=0∑w−1xi2i
函数
B
2
U
ω
(
x
⃗
)
B2U_ω(\vec{x})
B2Uω(x)将一个长度为
w
w
w的0、1串向量映射到非负整数来编码无符号数
补码编码
对向量$\vec{x}=[ x_{w-1},x_{w-1}, . . . ,x_{1},x_{0}] $
B
2
T
ω
(
x
⃗
)
=
−
x
w
−
1
2
w
−
1
+
∑
i
=
0
w
−
1
x
i
2
i
B2T_ω(\vec{x})=-x_{w-1}2^{w-1}+\sum_{i=0}^{w-1}x_i2^i
B2Tω(x)=−xw−12w−1+i=0∑w−1xi2i
最高位
x
w
−
1
x_{w-1}
xw−1也称符号位,权重值为
−
2
w
−
1
-2^{w-1}
−2w−1,是符号位,当其值被设置为1,则为负数,设置为0时,值为非负,
B
2
T
ω
B2T_ω
B2Tω是一个双射函数,也意味着每一个数的补码只对应一个编码,而每一个编码也唯一对应一个数。
补码转换为无符号数
对于满足
T
M
i
n
w
≤
x
≤
T
M
a
x
w
TMin_w≤x≤TMax_w
TMinw≤x≤TMaxw的
x
x
x有:
KaTeX parse error: No such environment: equation at position 8: \begin{̲e̲q̲u̲a̲t̲i̲o̲n̲}̲ T2U_w(x)=\left…
比如,我们看到
T
2
U
16
(
−
12345
)
=
−
12345
+
2
16
=
53191
T2U_{16}(-12345)=-12345+2^{16}=53191
T2U16(−12345)=−12345+216=53191,同时
T
2
U
16
(
−
1
)
=
−
1
+
2
16
=
U
M
a
x
w
T2U_{16}(-1)=-1+2^{16}=UMax_w
T2U16(−1)=−1+216=UMaxw
B
2
U
ω
(
x
⃗
)
和
B
2
T
ω
(
x
⃗
)
B2U_ω(\vec{x})和 B2T_ω(\vec{x})
B2Uω(x)和B2Tω(x)的差,从0到
w
−
2
w-2
w−2位将相互抵消,剩下一个值
B
2
U
ω
(
x
⃗
)
和
−
B
2
T
ω
(
x
⃗
)
=
x
+
x
w
−
1
(
2
w
−
1
−
(
−
2
w
−
1
)
)
=
x
w
−
1
2
w
B2U_ω(\vec{x})和-B2T_ω(\vec{x})=x+x_{w-1}(2^{w-1}-(-2^{w-1}))=x_{w-1}2^w
B2Uω(x)和−B2Tω(x)=x+xw−1(2w−1−(−2w−1))=xw−12w既可得到
B
2
U
ω
(
x
⃗
)
=
x
w
−
1
2
w
+
B
2
T
ω
(
x
⃗
)
B2U_ω(\vec{x})=x_{w-1}2^w+ B2T_ω(\vec{x})
B2Uω(x)=xw−12w+B2Tω(x)
扩展一个数字的位表示
short int 转换为int 需要转换数据的字长确要同时保证值不变,这就需要进行扩展数字的位操作了
无符号数的扩展是通过往拓展位置加0,而不码数的扩展则是向扩展位中加符号位,我们可以看下面一段代码
#include <stdio.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, size_t len)
{
size_t i;
printf("0x");
for (i = len-1; i < len; i--)
printf("%.2x", start[i]);
printf("\n");
}
int main()
{
short sx =-12345;
unsigned short usx=sx;
int x=sx;
unsigned ux=usx;
printf("sx=%d:\t",sx);
show_bytes((byte_pointer)&sx,sizeof(short));
printf("usx=%u:\t",usx);
show_bytes((byte_pointer)&usx,sizeof(unsigned short));
printf("x=%d:\t",x);
show_bytes((byte_pointer)&x,sizeof(int));
printf("ux=%u:\t",ux);
show_bytes((byte_pointer)&ux,sizeof(unsigned int));
return 0;
}
从这段代码的运行结果可以看出-12345的补码和53191表示在16位字长的值是相同的,而使用补码扩展时则会将扩展位置为1(负数的符号为1),无符号编码时则将扩展位置为0。
END