定点整数在计算机中的表示与运算
0 引言
对于每一个刚进入大学校门的大学生来讲,计算机系统的基本常识和基本操作都是一门必修的课程。但是,多年来,这些计算机相关基础知识在您的脑海中是否还记忆得十分清楚呢?
问题:十进制数-128在计算机中能否用8位(即一个字节的长度)二进制数来表示?如果可以,那么该怎样表示?
为了回答这个问题,笔者特意查询了许多相关资料,在网络上也搜集了许多网友的回答,但是其中有正确的也有错误的。笔者将在本文中将相关知识整理出来,纠正网上一些错误的或概念混淆的说法,以飨读者。
1 定点整数在计算机中的表示
在计算机中所处理的数据可以分为数值型和非数值型两类。其中,数值型数据是指数学中的代数值,具有量的含义,例如:128、-1024.8、4/5等;非数值型数据是指输入到计算机中的所有文字信息,没有量的含义,例如:作为字符处理的数字0—9,字母a—z,标点符号、图形、声音、视频等。
计算机系统内部采用二进制来存储和处理所有的数据,也就是说,一切输入到计算机中的数据都是由二进制数0和1排列组合而成的。
1.1 机器数与真值
在数学中,我们用正号“+”和负号“-”来区别正数和负数,而在计算机中,是采用符号位的方式来区分它们的,即:在符号位上用二进制数0来表示正数,用二进制数1来表示负数,符号位放在数字的最高位上。如果我们用8位二进制数来表示十进制数,则十进制数45和-45可以分别表示为:
+45→0010 1101
-45→1010 1101
这种连同符号位一起数字化了的数就称为机器数,由机器数表示的实际值称为真值。例如:机器数0010 1101的真值为十进制数+45或二进制数+101101,机器数1010 1101的真值为十进制数-45或二进制数-101101。
1.2 数的原码、反码和补码表示
在计算机中,对于有符号的机器数通常使用原码、反码和补码三种方式来表示,其主要目的是解决减法运算。任何正数的原码、反码和补码的形式都完全相同,负数则各自有不同的表示形式。
1.2.1 原码
正数的符号位用0表示,负数的符号位用1表示,其数值部分用二进制形式表示,这种表示方法称为原码。例如:十进制数+77和-77的原码可以分别表示为
+77→0100 1101(原码)
-77→1100 1101(原码)
用原码表示一个数字简单、直观,但是不能够用它直接对两个同符号数相减或两个不同符号数相加。例如:要计算十进制数36与-45的和,如果采用原码直接相加的方式
+36→0010 0100(原码)
-45→1010 1101(原码)
得1101 0001,这个机器数的符号位是1,表示负数,真值是1010001,相当于十进制数的81,结果合起来即为十进制数的-81,显然是不正确的。
为了解决两个同符号数相减或两个不同符号数相加的计算问题,引入了反码和补码的概念。
1.2.2 反码
正数的反码和原码相同,负数的反码是将该数字的符号位不变,其余各位依次取反得到。例如:十进制数+77和-77的反码可以分别表示为
+77→0100 1101(原码)→0100 1101(反码)
-77→1100 1101(原码)→1011 0010(反码)
不难推出,任何一个数的反码的反码等于这个数的原码。
1.2.3 补码
正数的补码和原码相同,负数的补码是将该数字的符号位不变,其余各位依次取反,然后加1得到。即:负数的补码是其反码加1。例如:十进制数+77和-77的补码可以分别表示为
+77→0100 1101(原码)→0100 1101(反码)→0100 1101(补码)
-77→1100 1101(原码)→1011 0010(反码)→1011 0011(补码)
不难推出,任何一个数的补码的补码等于这个数的原码。
1.3 定点整数在计算机中的运算
引入补码的概念之后,二进制数的加减法运算都可以采用加法来实现,并且两个数的“补码的和”等于它们“和的补码”。因此,在计算机中,加减法均采用补码来进行计算。例如:要计算十进制数36与-45的和,应先求出它们的补码
+36→0010 0100(原码)→0010 0100(反码)→0010 0100(补码)
-45→1010 1101(原码)→1101 0010(反码)→1101 0011(补码)
将补码相加,得1111 0111,结果也为补码表示,对其再进行一次求补运算,即
1111 0111(补码)→1000 1000(补码的反码)→1000 1001(补码的补码,即原码)
得到原码1000 1001,相当于十进制数的-9,结果正确。
由此可以看出,在计算机中的加减法运算可以统一为补码的加法运算,其符号位也参与运算,这是十分方便的。但是也应当注意,无论采用哪一种方式表示数值,当数的绝对值超过表示数的二进制位数所允许表示的最大值时,将会发生溢出,导致运算的错误。
2 8位二进制数可以表示的数值的范围
要讨论8位二进制数可以表示的机器数的范围,首先应该明确其表示的形式是原码、反码还是补码。因为,不同的表示形式其表示的数值范围也是不同的。下面就来逐步回答在本文引言部分所提出的问题。
2.1 原码的表示范围
8位二进制数可以表示的数值的原码的范围,用十进制数可以表示为[-127,127],其中0的表示有+0和-0两种,总计256个数字。详见下表。
2.2 反码的表示范围
8位二进制数可以表示的数值的反码的范围和原码相同,即每一个数的原码均对应着一个反码。详见下表。
2.3 补码的表示范围
8位二进制数可以表示的数值的补码的范围,用十进制数可以表示为[-128,127],总计256个数字。在这里最特殊的是十进制数-128,它只能够用补码的形式1000 0000来表示,它的原码和反码由于超出了8位二进制数所能表示的范围,因此无法由8位二进制数来表示。
表 8位二进制数可以表示的数值的原码、反码和补码略表
十进制数 | 二进制数原码 | 二进制数反码 | 二进制数补码 |
127 | 0111 1111 | 0111 1111 | 0111 1111 |
126 | 0111 1110 | 0111 1110 | 0111 1110 |
125 | 0111 1101 | 0111 1101 | 0111 1101 |
…… | …… | …… | …… |
2 | 0000 0010 | 0000 0010 | 0000 0010 |
1 | 0000 0001 | 0000 0001 | 0000 0001 |
0 | 0000 0000 | 0000 0000 | 0000 0000 |
-0 | 1000 0000 | 1111 1111 | (不可表示) |
-1 | 1000 0001 | 1111 1110 | 1111 1111 |
-2 | 1000 0010 | 1111 1101 | 1111 1110 |
…… | …… | …… | …… |
-125 | 1111 1101 | 1000 0010 | 1000 0011 |
-126 | 1111 1110 | 1000 0001 | 1000 0010 |
-127 | 1111 1111 | 1000 0000 | 1000 0001 |
-128 | (不可表示) | (不可表示) | 1000 0000 |
3 结论
综上所述,如果有人提到8位二进制数所能表示的数值的范围,回答应该有两个,即:原码和反码的表示范围是[-127,127],共256个数,其中0有+0和-0两个;补码的表示范围是[-128,127],其中-128不存在原码和反码。然而在计算机中,负数全部都以补码的形式存储和参与运算,因此通常人们所说的8位二进制数所能表示的数值范围就是补码的表示范围,亦即[-128,127]。