2.2.3 二进制计数系统
我们对基数为2的(二进制)计数系统并不陌生。尽管如此,还是有必要快速回顾一下。二进制计数系统的原理与十进制计数系统一致,差别在于二进制只用到了数字符号0和1(而不是0~9)及2(而不是10)的幂。
那么为什么要费心了解二进制呢?毕竟,几乎每一种计算机语言都允许程序员使用十进制表示形式(十进制表示形式会被自动转换为内部的二进制表示形式)。虽然可以自动转换,但大多数现代计算机系统和I/O设备之间的通信使用的是二进制,运算电路操作的也是二进制数据。许多算法采用二进制表示形式才能正确地运行。充分理解二进制表示形式才能写出好代码。
1.十进制和二进制表示形式的转换
要理解计算机的工作,需要知道十进制和二进制表示形式是如何相互转换的。
要将二进制数值转换为十进制,需要在二进制字符串中逢1加2i,这里的i是1这个数字的位置,从0开始。例如,二进制数值11001002等于:
1×27+1×26+0×25+0×24+1×23+0×22+1×21+0×20
即
128+64+8+2
即
20210
将十进制数值转换为二进制也很简单。将十进制表示形式转换为对应的二进制表示形式的算法如下:
1.如果数值为偶数,则填写一个二进制字符0。如果数字为奇数,则填写一个二进制字符1。
2.将数字除以2,舍去小数部分或余数。
3.如果商为0,则转换完成。
4.如果商不为0且为奇数,则在二进制字符串之前填1。如果商不为0且为偶数,则在二进制字符串之前填0。
5.回到步骤2并重复后面的步骤。
例如,将十进制数值202转换为二进制:
1.202为偶数,因此填0并除以2(101):0
2.商101为奇数,因此填1并除以2(50):10
3.商50为偶数,因此填0并除以2(25):010
4.商25为奇数,因此填1并除以2(12):1010
5.商12为偶数,因此填0并除以2(6):01010
6.商6为偶数,因此填0并除以2(3):001010
7.商3为奇数,因此填1并除以2(1):1001010
8.商1为奇数,因此填2并除以2(0):11001010
9.商为0,算法转换完成,得到11001010。
2.让二进制数值便于理解
20210和11001002虽然数值相等,但一眼就能看出来,十进制表示形式比二进制紧凑。我们需要通过一种方式让二进制数值中的数字(位)更简短、更容易理解。
在美国,为了让较大数值容易理解,很多人把数字分成三个一组,用逗号隔开。例如,1,023,435,208比1023435208更容易阅读和理解。本书也采用了类似的约定,将二进制字符串按四位一组用下画线分隔。例如,二进制数值10101111101100102记为1010_1111_1011_00102。
3.编程语言的二进制数值表示
上文中都是用下标符号(没有下标则代表十进制数值)表示二进制数值。但程序文本编辑器或编程语言编译器通常是无法处理下标的,因此,在标准ASCII文本文件中需要使用不同的方式来表示基数。
通常,只有汇编语言编译器(汇编器)允许程序使用二进制字面值常量。[1]由于不同的汇编器之间的差异很大,因此汇编语言程序中存在多种表示二进制字面值常量的方法。本书示例使用的是MASM和HLA,因此我们也采用它们的二进制表示约定。
MASM使用以b或B结尾的二进制数字(0和1)字符串表示。MASM源文件中9的二进制表示为1001b。
在HLA中,需要在二进制数值的前面加一个百分号(%)。HLA还允许在二进制字符串中插入下画线以提高可读性,例如: