1.5 数和字符的表示
1.5.1 数的表示
1.十进制和二进制
程序的数据和代码在计算机内部都是以0、1表示的。而在编程语言中,数的表示方式有多种。例如,可以用日常生活中常用的“十进制(Decimal)”,即用10个不同的数字0、1、2、...、9表示一个数。对于小于10的数,可以直接用这10个不同数字中的一个来表示或区分就可以了,即1位数字就可以表示不超过10的数。但如果一个数超过了10,就需要用两位数字、三位数字等多位数字来表示,即用“逢十进一”的多位数表示。例如,一个整数329意思是“3个100”加“2个10”加“1个9”,可以表示成10i的多项式:
329=3×100+2×10+9=3×102+2×101+9×100
但在计算机中,由于计算机硬件,即晶体管元器件,只有“开”和“关”两种状态,也就是在说,1个晶体管元器件的开和关状态只能区分两种不同情况,相当于只能表示0和1两个数字。如果要表示更大的数字,则可以采用“逢二进一”的方法,即采用多个晶体管元器件,即多个0和1的排列来表示一个很大的数字。这种用两个数字0和1表示数的方法就称为“二进制”表示法。例如,二进制数1011可以表示成2i的多项式:
1011=1×23+0×22+1×21+1×20=1×8+0×4+1×2+1×1=11
即相当于十进制数11。
1位二进制位经常也称为1比特(Bit,简记为b),而8位二进制位经常也称为1字节(Byte,简记为B)。8位二进制数对应的十进制数如表1-1所示。
表1-1 8位二进制数对应的十进制数
使用前7位二进制位可以表示0到127共128个不同数字,使用全部8位二进制位可以表示一共256,即28个不同的数。如果有n位二进制位,则可以表示2n个不同的数,如正整数0到2n-1。
2.十六进制
当处理更大的二进制数时,则二进制数的位数太多不方便使用。例如:
101101011101100111100101
如果表示成十进制数11917797,则只要8位。然而,十进制数在某些情况下也不方便,如希望将从右往左的第17位二进制位设置成1,就很难用十进制做到。解决方法就是采用“十六进制”,即用十六个不同的数字来表示一个数,即用十进制的10个数字0、1、2、…、9加上英文字母的前6个字母A(a)、B(b)、C(c)、D(d)、E(e)、F(f)来分别表示一个数(英文字母不区分大小写)。如表1-2所示是十六进制、十进制和二进制之间的对应关系。
表1-2 十六进制、十进制和二进制的对应关系
因为1位十六进制数对应4位二进制数,所以可以将任何1个二进制数按照4位一组的方式以十六进制形式表示。例如:
101101011101100111100101
对应十六进制表示法,很简单就可以写出来:
b 5 d 9 e 5
对这种十六进制数可以很容易地设置其对应二进制的第17位为1(思考一下?),也可以将十六进制数采用如下方式计算出对应的十进制数的值:
b×165+5×164+d×163+9×162+e×161+5×160
1.5.2 字符的表示
在计算机中,各种字符,如英文字母、数字(0、1、2、...、9)、一些特殊字符(#、/、换行符、制表符等键盘上可见字符)都是以一串二进制数表示的。
1.ASCII码
1960年代,American Standard Code for Information Interchange(ASCII)约定使用7位二进制数表示128个不同的字符。
原始的7位ASCII对于英语没有任何问题,但是对于法语、德语等语言字符就不够用了,于是提出了扩展的用8位二进制数表示字符的扩展ASCII字符编码。
但对于某些国家语言的字符很多情况下(如汉字将近88000个),8位ASCII字符编码就不够用了,为了克服原始的ASCII的缺陷,1990年人们提出了“统一字符编码”(Universal Character Set, UCS)。UCS是ISO 10646标准,UCS字符的编码长度为32位。
2.UCS和Unicode
UCS定义了字符和编码点(Code Point)的整数值的映射关系。编码点和编码(Code)并不是一回事,编码点是一个整数值,而编码是用一系列字节表示一个编码点的方式。当数值不超过256时编码点用一字节就可以表示,如果用4字节而不是1字节存储这些值就浪费了。因此,编码是有效存储编码点的方式。
Unicode是一个标准,不仅定义了一个字符集及其字符的编码点(字符的编码点等同于UCS对应字符的编码点),还定义了多种表示编码点的编码方式。编码点不仅可以表示所有语言的所有字符,还可以表示不同的图形符号,甚至表情符号。大多数语言字符都能用16位编码(Code)表示。
Unicode提供了多种编码方法,但也造成了理解上的困惑,最广泛使用的Unicode编码方式包括UTF-8、UTF-16、UTF-32。其中,每个编码方式都可以表示Unicode字符集中的所有字符。
● UTF-8表示一个字符采用的是变长的字节序列(用1~4字节表示1个字符),其中,ASCII字符的编码使用1字节表示,和对应的ASCII编码是一样的。大多数网页的文本都采用UTF-8编码方式。
● UTF-16用1个或2个16位(16-bit)编码表示一个字符。UTF-16包含了UTF-8。
● UTF-32最简单,用1个32位(32-bit)编码表示所有字符。
如表1-3所示是UniCode编码点和UTF-8编码的关系。
表1-3 UniCode编码点和UTF-8编码的关系
例如,汉字的“中”的十六进制表示是“4E2D”,其二进制形式是“0100111000101101”,其UTF-8编码占用的是3字节,只要将其二进制位从后往前填入相应的“x”的位置就得到了其对应的UTF-8编码11100100 10111000 10101101。
如表1-4所示是字符“A”和汉字“中”的UniCode编码点及UTF-8编码。
表1-4 字符A和汉字“中”的UniCode编码点及UTF-8编码