我们很自然地把它理解为:
或者,使用10的幂来表示:
注意任何数(除了0)的0次幂都是1。
数据中的每个数字表示从0到9的值,这样我们有10个不同的数字,那就是我们把它称为“十进制”的原因。每个数字可以通过10的某次幂来决定它的位置。这听起来很复杂,但实际上并不是这样的。这正是当您读一个数字的使用认为是理所当然的事情,您甚至都不用仔细思考它。
类似地,使用二进制编码就像上面所说的那样,值13是这样编码的:
每一个位置有两个数字可以选择,所以我们称它为“二进制”。因此,它们的位置是这样决定的:
1101 =1 × 8 + 1 × 4 + 0 × 2 + 1 × 1 = 13(十进制)
我们讨论一些偏外的话题:对二进制数字的表示方法。计算机通常使用二进制来表达数据,但是在实际中如果使用像这样的二进制:
那将是一件痛苦的事,并且很容易出错。通常计算机使用一个基于二进制的表达方式:八进制,或更通常使用的,十六进制。
这一件听起来挺狡猾但实际上又很简单的事。如果不是这样的话,我们就不会这样使用了。在平常的十进制体系中,我们有10数字(0到9)按以下方式构成排列:
在八进制中,我们只有八个数字(0到7)按以下方式构成排列:
也即是说,八进制的“10”相当于十进制的“8”,八进制的“20”相当于十进制的“16”,以此类推。
在十六进制中,我们只有十六个数字(0到9,然后是从a到f)按以下方式构成排列:
也即是说,十六进制的“10”相当于十进制的“16”,十六进制的“20”相当于十进制的“32”。
在定义了无符号二进制数后,我们就要着手定义负数了,或称为“有符号整数”。最简单的一个方法是保留一个位来表示数值的符号。这个“符号位”可以位于数值的最左边,当然也可以位于数值的最右边。如果这个符号位为0,表示数值是正的,如果这个符号位为1,表示数值是负的。
这样做是可以的,虽然从人类的角度来看是最明显的解决方案,但是它对于计算机来说有可能带来一些难度。例如,这种编码使得0可以有正负两种。人们可能对此感到不可思议,但是这对计算机来说是适应的。
对计算机来说,更自然的表达方式是对给定的位数的二进制数按其范围分成两半,其中前一半用来表示负数。例如,在4位数值中,你可以得到:
我们得到了一个“有符号整数”数字系统,使用所知道的,为了一些不是很重要的原因,“补码”编码方式。对16位有符号数字编码来说,我们可以得到范围为-32,768到32,767的有符号数字。对一个32位的有符号编码系统来说,我们可以为从-2,147,483,648到2,147,483,647的数编码。
与只改变符号位来表示负数的编码方式相比,“补码”编码方式与之有所不同。例如对于-5来说,只对符号位编码,应该是:
但是对于“补码”编码方式来说,则是:
这对于符号编码来说是-3。关于为什么计算机要使用补码这种编码方式我们会在后面解释。
所以,我们可以以二进制方式来表示正负两种不同的数值。请记住对于一个二进制数来说,只有两种解释方式。如果在内存中有一个这样的二进制数值:
这种格式通常被用于商业计算(例如在电子表格或COBOL中);因为在这里,丢弃小数位来记录金钱是不能接受的。因此了解二进制如何存贮小数是十分有用的。
首先去我们必须决定要用多少位来存贮小数部分和多少位来存储整数部分。假设我们使用32位来表示这种格式,那么我们用16位表示整数部分,16位来表示小数部分。
小数部分怎么使用呢?这沿用了表示整数的方式:如果8位接下来是4位,是2位,1位,那么当然接下来就是半位,1/4位和1/8位等等了。
例如:
有一点棘手的是,如果您要表达1/5(十进制的0.2),那您不能得到精确的数值表达方式。最好的方法只能是:
然而不,您不能这样做,即使您有更多的数位来表达。问题是,一些小数使用二进制的方式不能精确地表达出来。除非您使用一个特殊的办法。这个特殊的办法是分别使用两个数字来表达小数:一个是分子,一个是分母。然后您可以使用学校学习的加、减、乘、除来得到它们。然而,这些方法不能表达更高级的数字(例如平方根),或者如果这两个分母的最小公倍数很大的话,那就难以使用。这就是使用定点小数表达小数的缺点。
当我们使用了有符号和无符号的数值表达方式时。如果遇到连32位也不足以表达的大范围的数,或也许可以表达,但我们必须为此放弃小数位时,我们可以选择的以获得更大范围的数值的表达方式的方法是使用“浮点小数”格式而抛弃“定点小数”格式。
对于低级语言的编程者来说,他们要担心有符号和无符号、定点和浮点数的运算。他们必须使用十分不同的代码来实现操作。
但是,对高级语言的编程者来说,诸如LISP和Python提供了一些列诸如“有理数”、“复数”之类的抽象数据类型。而他们可以断言他们的系统可以使用数学操作做正确的运算。由于操作符重载,数学运算可以应用于任何数字——无论是有符号的、无符号的、有理数、定点小数、浮点小数或复数。
我们已经得到不同的方法来存储数据了,那么文本呢?我们怎么存储姓名、地址或写给朋友的信件呢?
当然,如果您还记得位是位的话,我们没有理由不能使用位来表达字母“A”或“?”或“Z”之类的。因为很多计算机每次处理一个字节,所以使用单字节的数据来表达单个字母会很方便。我们可以使用这个:
来表示字母“F”。计算机使用这样的“字符编码”来向显示程序传送要求的文本。
下面是一个用来存储西方字母的标准二进制编码,就是通常所说的“美国信息交换标准码”(英文简称“ASCII”),下面的编码为ASCII编码,使用“d”表示十进制编码,“h”表示十六进制代码,“o”表示八进制代码:
上面这个列表的最左边有一个些奇怪的字符,例如“FF”和“BS”,这些都不是文本字符。相反,它们是控制字符,也就是说当这些字符发送到特定的设备时,它将产生一些动作。例如“FF”表示换页,或弹出;“BS”表示退格,而“BEL”表示一个响声。在一个文本编辑器中,它们会显示成一个白色或黑色的方块,或笑脸、音符或其它一些奇怪的符号。要打出这些字符,可以使用CTRL键和一个合适的代码。例如同时按住“CTRL”和“G”,或简写成“CTRL-G”或“^G”可以打出一个BEL字符。
上面这个ASCII码表示定义了128个字符,这意味着ASCII码只需要7位。但是,很多计算机都以字节为单位存储信息。这个额外的一位可以定义第二个128个字集,一个“扩展”字集。
在实际中,有很多不同的“扩展”字集,提供很多例如数学符号等的符号或非英语字符。这个扩展字集并没有进行标准化,并经常会引起混淆。
这个表格强调了这篇文章的主题:位就是位。这样的话,您可以使用位来表示字符。您可以把特殊的代码描述成特殊的十进制、八进制和十六进制,但是它们仍然是相同的代码。这些数值的表达,无论是十进制、八进制或十六进制,都只是相同的位的表达。
当然,您可能在一段话中表达很多的字符,例如:
这只是简单的替换成ASCII码,表示成:
计算机把这种ASCII“字符串”以连续空间的“数组”来存储。一些应用程序可以包括一个二进制数值表示字符串的长度,但是更通常的做法是使用一个表示结尾的字符NULL(ASCII表中的0字符〕表示字符串的结束。