计算机数值编码

计算机数值编码是指电子计算机内部表示数字的方式。通常数值会储存为位元组序列，而以组成它们的位元数给以名称，例如32位整数、64位浮点数。对于计算机处理器指令集所使用的位元编码，通常需要将其格式再转换以供外界的使用者来判读，例如打印和显示。对于纸笔书写看似相同的文字符号或数值，在不同类型的电子计算机处理器内部中，可能有不同的约定用于整数和实数。大多数计算都是使用适合处理器暂存器的数码格式来执行，但是某些软件系统允许使用多种储存方式，来表示任意大数。
二进制表示法.
电脑会将资料用一串二进制的数字来表示，二进制数字是由位元所组成，也会将位元组合成较大的单位，像是位元组。
计算机的基本储存单位是「位元」（bit），通过开关变化设置表达值0或1。位元的概念可以表示为1或0、开或关、是或不是、真或假等等。
一个位元可以表示二个值，而几个位元可以表示较大的数值。例如，三个位元就可以表示八个不同的数值，如表1所示。位元数越多，可以表达的数字也就越多，可以表达的数字会随著位元数指数成长， n位数的二进制数字可以表达2n种可能的数字，如表2所示。
为了方便理解，会将特定个数的二进制数字组合起来，变成较大的单位，且有其名称。
字节（byte）是长度可以表示字符的二进制位数组。在现有大部份的电脑中，字节是由8个位元所组成，由于字节的定义和表示字符所需要的位元个数有关，有些较旧的电脑可能有不同的字节定义。在许多计算机系统结构中，字节是最小的，也就是位址定址的最小单位。例如，即使64位元处理器一次可以处理64位元，仍然将其记忆体以8位元为单位来分割。这就是字节定址的记忆体。以往有许多CPU是以8位元的整数倍来读取资料。字节由8个位元所组成的情形非常常见，但不是标准化的定义，因此有出现八位元（octet）的名称，明确说明是由8个位元所组成的单位。
是由4个位元所组成的单位。4个位元可以表示16个值，因此nibble也会称为十六进制数字。
八进制和十六进制数.
对二进制数字的表示方法。计算机通常使用二进制来表达数据，但是在实际中如果使用像这样的二进制：
这些很长的数字对于人手计算及观看上会很容易出错。因此计算机会使用八进制或更常使用的十六进制的，一个基于二进制的表达方式。
这个简单的解决方法十分有效，在平常的十进制体系中，有10数字（0到9）按以下方式构成排列：
在八进制中，只有八个数字（0到7）按以下方式构成排列：
也即是说，八进制的「10」相当于十进制的「8」，八进制的「20」相当于十进制的「16」，以此类推。
在十六进制中，只有十六个数字（0到9，然后是从a到f）按以下方式构成排列：
也即是说，十六进制的「10」相当于十进制的「16」，十六进制的「20」相当于十进制的「32」。
这些表示数值的方法都是表位置的系统，但是它们使用的不是像十进制那样的10，而是分别使用8和16。例如：
于八进制来说，他们刚好和3位元二进制有一个完美的对应关系：
相似地，一个十六进制数刚好和一个4位元的二进制数对应。
因此，把一个很长的二进制数转换成一个八进制就变得很简便，例如：把二进制1001001101010001转化成八进制：
转换成十六进制则是：
因为要把它转换成十进制（37,713）比较复杂，八进制和十六进制使得转换二进制机器级的数字变得简单方便。
有符号整数和补码.
在定义负数中，有两种普遍的方法，分别是「无符号整数」及「有符号整数」。
无符号整数.
这个方法保留了一个位来表示数值的符号。这个「符号位」可以位于数值的最左边，也可以位于数值的最右边。如果这个符号位为0，表示数值是正的，如果这个符号位为1，表示数值是负数。然而这样做对于计算机来说有可能带来一些缺点。这种编码使得0可以有正负两种，有符号整数会浪费掉一个表达数值的范围
有符号整数.
更优胜的表达方式是对给定的位数的二进制数按其范围分成两半，其中前一半用来表示负数。例如，在4位数值中，你可以得到：
这个有符号整数的系统使用所知道的「补码」编码方式。
对16位元有符号数字编码来说，可以为从-32,768到32,767的数编码。
对一个32位元的有符号编码系统来说，可以为从-2,147,483,648到2,147,483,647的数编码。
与只改变符号位来表示负数的编码方式相比，「补码」编码方式与之有所不同。例如对于-5来说，只对符号位编码，应该是：
但是对于「补码」编码方式来说，则是：
这对于符号编码来说是-3。关于为什么计算机要使用补码这种编码方式会在后面解释。
所以，可以以二进制方式来表示正负两种不同的数值。请记住对于一个二进制数来说，只有两种解释方式。如果在内存中有一个这样的二进制数值：
-- 这只能解释为十进制的「13」或「-5」。
定点小数.
这种格式通常被用于商业计算（例如在电子表格或COBOL中）；因为在这里，丢弃小数位来记录金钱是不能接受的。因此了解二进制如何存贮小数是十分有用的。
首先必须决定要用多少位元来存贮小数部分和多少位元来存储整数部分。假设使用32位元来表示这种格式，那么用16位元表示整数部分，16位元来表示小数部分。
小数部分可以沿用表示整数的方式：如果8位元接下来是4位元，是2位元，1位元，接下来就是半位元，1/4位元和1/8位元等等。
例如：
如果要表达1/5（十进制的0.2），那么不能得到精确的数值表达方式。最好的方法只能是：
一些小数使用二进制的方式不能精确地表达出来。除非使用一个特殊的办法。这个特殊的办法是分别使用两个数字来表达小数：一个是分子，一个是分母。然后可以使用学校学习的加、减、乘、除来得到它们。然而，这些方法不能表达更高级的数字（例如平方根），或者如果这两个分母的最小公倍数很大的话，那就难以使用。这就是使用定点小数表达小数的缺点。
浮点小数.
当使用了有符号和无符号的数值表达方式时。如果遇到连32位元也不足以表达的大范围的数，或也许可以表达，但必须为此放弃小数位时，可以选择的以获得更大范围的数值的表达方式的方法是使用「浮点小数」格式而抛弃「定点小数」格式。
在十进制中，对以下的表达方式很熟悉：
或简写成：
这表示「1.103402乘以一个1后面跟着5个零的数」。可以得到一个确定的称谓「尾数」的数值（1.1030402），乘以一个10的某个幂级数(E5，表示105或100,000），也就是「幂级数」。如果使用一个负的幂级数，那就意味着乘以该正级数的倒数。例如：
使用这种定义的好处是可以得到更大范围的数值，虽然尾数部分的精确度受到影响。相似的原理可以应用于二进制中为计算机使用。人们设计了很多方式，但是作常用的是由美国电器和电子工程师协会定义的一种方法。它对64位浮点格式的定义是：
下面使用一个例子来了解计算机如何使用内存的8字节存储这些数字：
其中的「S」表示符号位，「X」表示指数位（阶码？），「m」表示尾数位。一旦这些数字被读取，它将转换成：
这个方式提供的数字范围为：
这种方式也定义了一些不是数字的值，例如「NaNs」（「不是一个数字」）。这通常用来返回表示数字溢出的信息。一些程序使用32位元浮点小数。最普遍的是使用32位元尾数，1位元符号位，8位元阶码和「超127」格式。它提供7位十进制数字。
数字转换时使用：
它的范围为：
通常可以把32位元的二进制浮点数称为「单精度」浮点数，而把64位元的二进制浮点数称为「双精度」浮点数。如果使用real的时候，通常表示双精度的浮点数；而使用float的时候，通常指单精度的浮点数。
但是要记住的是，浮点数在计算机的存储是连续的：当计算机内存中有一个64位元数据时，它可能是一个双精度的浮点数，也可能是两个单精度的浮点数，或4个有符号或无符号的整数，或其它8位的数据，这取决于计算机如何读取它们。如果计算机把4个无符号整数以双精度浮点小数方式读出的话，它可以得到一个双精度浮点小数，但这个数据可能是一个垃圾数据。
所以，现在虽然已经解决了正、负数的存贮方式，但是对于浮点数来说，仍然存在一些与整数一样的缺陷，例如：
计算机不是万能的，它只是一部机器，并要符合一定的规则和受到一定的限制。在计算机虽好的解决方法下也有一些不可避免的不精确。
编程语言中的数.
对于低级语言的编程者来说，他们要担心有符号和无符号、定点和浮点数的运算。他们必须使用十分不同的代码来实现操作。
但是，对高级语言的编程者来说，诸如LISP和Python提供了一些列诸如「有理数」、「复数」之类的抽象数据类型。而他们可以断言他们的系统可以使用数学操作做正确的运算。由于操作符重载，数学运算可以应用于任何数字——无论是有符号的、无符号的、有理数、定点小数、浮点小数或复数。
字符编码：ASCII和字符串.
对于字符，例如姓名、地址或写给朋友的信，如果还记得几位是几位的话，当然可以使用数字来表达字符「A」或「?」或「Z」。计算机同理。计算机每次处理一个字节，所以使用单字节的数据来表达单个字符会很方便。可以使用这个：
来表示字符「F」。计算机使用这样的「字符编码」来向显示程序传送要求的文本。
下面是一个用来存储西方字母的标准二进制编码，称为「美国信息交换标准码」（英文简称「ASCII」），下面的编码为ASCII编码，使用「d」表示十进制(decimal)编码，「h」表示十六进制(hexadecimal)代码，「o」表示八进制(octal)代码：
上面这个列表的最左边有一个字符，例如「FF」和「BS」，这些都不是文本字符。相反，它们是控制字符，当这些字符发送到特定的设备时，它将产生一些动作。例如「FF」表示换页，或弹出；「BS」表示退格，而「BEL」表示一个响声。在一个文本编辑器中，它们会显示成一个白色或黑色的方块，或笑脸、音符或其它替换符。要打出这些字符，可以使用CTRL键和一个合适的代码。例如同时按住「CTRL」和「G」，或简写成「CTRL-G」或「^G」可以打出一个BEL字符。
上面这个ASCII码表示定义了128个字符，这意味着ASCII码只需要7位元。但是，很多计算机都以字节为单位存储信息。这个额外的一位元在某些英语以外的国家被用于二个128个字集，一个「扩展」字集，例如EASCII
除了EASCII，还有很多不同的「扩展」字集，提供很多例如数学符号等的符号或非英语字符。这个扩展字集并没有进行标准化，并经常会引起混淆，同样的字串在不同的装置上显示不同的内容
这个表格强调了位元就是位元。这样的话，可以使用位来表示字符。可以把特殊的代码描述成特殊的十进制、八进制和十六进制，但是它们仍然是相同的代码。这些数值的表达，无论是十进制、八进制或十六进制，都只是相同的位的表达。
在一段话中表达很多的字符，例如：
以ASCII码，会表示成：
计算机把这种ASCII「字符串」以连续空间的「数组」来存储。一些应用程序可以包括一个二进制数值表示字符串的长度，但是更通常的做法是使用一个表示结尾的字符NULL（ASCII表中的0字符〕表示字符串的结束。