嵌入式软件中负数如何存储
在计算机中,负数通常使用补码来表示。下面以8位有符号数为例,展示-1、-2和-3的二进制和十六进制形式,以及它们的计算方法。
十进制数 | 二进制原码 | 二进制反码 | 二进制补码(内存中存储的形式) | 十六进制补码 |
-1 | 1000 0001 | 1111 1110 | 1111 1111 | 0xFF |
-2 | 1000 0010 | 1111 1101 | 1111 1110 | 0xFE |
-3 | 1000 0011 | 1111 1100 | 1111 1101 | 0xFD |
计算负数的补码遵循以下固定步骤:
原码:先写出该负数绝对值的二进制表示(即对应的正数),最高位(符号位)设为1。例如,对于-3:3的二进制是 0000 0011。-3的原码是 1000 0011。
反码:保留符号位不变,将原码的数值位(后7位)按位取反(0变1,1变0)。-3的原码 1000 0011取反后得到反码 1111 1100。
补码:在反码的基础上,最低位加1。-3的反码 1111 1100加1后得到最终的补码 1111 1101。
计算机采用补码主要有三个重要原因:
统一加减法:可以将减法运算转换为加法运算,CPU只需一个加法器就能处理 both 加法和减法,简化了硬件设计。例如,计算
3 - 3
等同于计算3 + (-3)
。用补码计算:0000 0011
(3的补码) +1111 1101
(-3的补码) =1 0000 0000
。由于是8位系统,最高位的进位1被自然舍弃,结果就是0000 0000
(0),结果正确。解决0的编码唯一性:在原码表示中,0有
+0
(0000 0000
)和-0
(1000 0000
)两种表示,这会造成浪费和混淆。而在补码中,-0
(1000 0000
)加1后进位,同样得到0000 0000
,从而保证了0的编码唯一性。扩展表示范围:8位补码可以表示的范围是-128到+127,比原码的-127到+127多表示一个数(-128)。
需要特别注意的是,一个负数的十六进制表示长度取决于数据类型的位数。
在8位系统(如
char
)中,-2 表示为0xFE
。在16位系统(如
short
)中,-2 表示为0xFFFE
。在32位系统(如
int
)中,-2 表示为0xFFFFFFFEQIAN
。
这是因为在高位会进行符号扩展,即用1来填充多余的位数,以保持其负数值不变