A 级计算机 2009/AQA/处理和编程技术/计算机中的数据表示
如你所知,我们通常计数的数字系统是 **十进制**,而计算机使用的数字系统,二进制,是 **二进制**。**十六进制** 是 **十六进制** 数字系统。在十六进制中,使用数字 0-9,就像在十进制中一样,但字母 A-F 也用来表示数字 10-15。下表显示了十进制中的数字 0-16,以及它们的二进制和十六进制等价物
十六进制 | 二进制 | 十进制 |
---|---|---|
0 | 0000 | 0 |
1 | 0001 | 1 |
2 | 0010 | 2 |
3 | 0011 | 3 |
4 | 0100 | 4 |
5 | 0101 | 5 |
6 | 0110 | 6 |
7 | 0111 | 7 |
8 | 1000 | 8 |
9 | 1001 | 9 |
A | 1010 | 10 |
B | 1011 | 11 |
C | 1100 | 12 |
D | 1101 | 13 |
E | 1110 | 14 |
F | 1111 | 15 |
10 | 10000 | 16 |
你可能会从表中注意到,一个十六进制数字可以精确地表示 4 个二进制位。十六进制对我们来说是一个有用的二进制简写方法,并且使处理长二进制数字变得更容易。
由于 4 个二进制位由一个十六进制数字表示,因此在两者之间进行转换非常简单。你可以将二进制位分组为 4 位一组,从右边开始,并在需要时在左边添加额外的 0,然后将每组转换为其十六进制等价物。例如,数字 110110011110101 可以这样写
0110 1100 1111 0101
然后通过使用上面的表格,你可以将每组 4 个位转换为十六进制
6 C F 5。
所以二进制数 0110110011110101 在十六进制中是 6CF5。我们可以通过将两者都转换为十进制来检查这一点。首先我们将转换二进制数,因为你已经知道如何做到这一点
32768 | 16384 | 8192 | 4096 | 2048 | 1024 | 512 | 256 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 1 |
通过将列相乘,然后将结果相加,答案是 27893。
请注意,列标题都是 2 的幂,, , , ,依此类推。要从十六进制转换为十进制,我们必须使用以 16 为底的幂作为列标题,如下所示
4096 | 256 | 16 | 1 |
---|---|---|---|
6 | C | F | 5 |
(你应该记住 A-F 的值)
将它们全部加起来得到 27893,表明 0110110011110101 等于 6CF5。
要从十进制转换为十六进制,建议先将数字转换为二进制,然后使用上面的简单方法从二进制转换为十六进制。
- 注意:使用十六进制是因为它比纯二进制更容易让人理解。它 **不** 占用更少的内存空间,只在纸面上占用更少的空间!
计算机完全用二进制工作。这意味着它只使用 1 和 0,并且没有计算机可以使用 - 或 + 符号。计算机必须以不同的方式表示负数。
我们可以通过将最高有效位设为 **符号位** 来表示二进制中的负数,该符号位将告诉我们该数是正数还是负数。8 位数的列标题将如下所示
-128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
---|---|---|---|---|---|---|---|
1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 |
在这里,最高位为负数,其余各位为正数。从 -128 开始,并像正常一样添加其他位。上面的例子在十进制中是 -67。-1 的二进制表示为 11111111。
请注意,只有当数字被指定为 **带符号** 时,才使用最高位作为符号位。如果数字是 **无符号** 的,则最高位为正数。
要找出补码的数值,我们必须首先记下它的符号位(最高位,最左边的位)。如果是 0,则该数为正数,如果是 1,则该数为负数。
0000 0101 (positive) 1111 1011 (negative)
要找出负数的数值,我们必须找到并保留最右边的 1 以及它右侧的所有位,然后翻转它左侧的所有位。以下是一个示例
1111 1011 find the right most one 1111 1011 0000 0101 flip all the bits to its left
现在我们可以计算出这个新数的数值,它是
128 64 32 16 8 4 2 1 0 0 0 0 0 1 0 1 4 + 1 = −5 (remember the sign you worked out earlier!)
更复杂的示例如何?
1111 1100 find the right most one 1111 1100 0000 0100 flip all the bits to its left
128 64 32 16 8 4 2 1 0 0 0 0 0 1 0 0 4 = −4 (remember the sign you worked out earlier!)
因此我们知道如何计算出给定负数的数值。我们如何计算出正数的负值?就像这样……
取正数的二进制形式
0000 0101 (5) 0000 0101 find the right most one 0000 0101 1111 1011 flip all the bits to its left
因此现在我们可以看到正数和负数之间的区别
0000 0101 (5) 1111 1011 (−5)
在二进制中,用一个数减去另一个数可能会变得非常混乱。
X (82 denary) 0101 0010 Y (78 denary) 0100 1110 −
从 X 中减去 Y 的更简单方法是将 Y 的负值 **加** 到 X 的值上
X−Y = X+(−Y)
为此,我们首先需要找出 Y 的负值
0100 1110 find the right most one 0100 1110 1011 0010 flip all the bits to its left
现在再次尝试求和
0101 0010 X( 82 denary) 1011 0010 + Y(−78 denary) 0000 0100 (¹)¹¹¹ ¹ the one carried over the bit 9 is ignored
结果为
128 64 32 16 8 4 2 1 0 0 0 0 0 1 0 0 4 = 4 = 82-78
到目前为止,我们只处理了整数,即 **整数**。我们需要一种方法来在计算机系统中存储 **实数**。
首先,我们应该看看十进制中表示分数的一种方法
10 | 1 | |||
---|---|---|---|---|
1 | 2 | . | 7 | 5 |
正如你所见,列标题已扩展到 和 。我们可以在二进制中做同样的事情,列标题为 、,等等。因此,12.75 的二进制表示为
8 | 4 | 2 | 1 | |||
---|---|---|---|---|---|---|
1 | 1 | 0 | 0 | . | 1 | 1 |
请注意,对于小数点后相同数量的位,二进制数的精度较低。它只能取 4 个不同的值,而十进制数可以用两位数进行 100 种不同的划分。
如果你学习物理学或化学等其他科目,你可能会遇到这样的浮点数
(Planck's constant)
第一个位定义了数字的非零部分,称为 **尾数**,第二部分定义了我们希望移动小数点的位数,这称为 **指数**,当将小数点向右移动时可以为正,当将小数点向左移动时可以为负。
如果你想完整地写出这个数字,你必须将小数点在指数中向左移动 34 位,得到
写出这些数字需要花费大量时间,而且人眼很难辨别出到底有多少个零。因此,当我们可以接受一定程度的精度(6.63 = 3 位有效数字)时,我们可以用少量的数字存储像普朗克常数这样的多位数。你总是在权衡数字的范围(或范围)与其精度(有效位数)。
二进制数也是如此,而且更重要。在处理数字及其计算表示时,你必须始终注意数字在内存中会占用多少空间。正如我们在上面的例子中看到的,一个数字的非浮点数表示可能会占用不切实际的位数,想象一下存储 在二进制中需要多少位数?(别担心,这个问题是修辞性的)
一个二进制浮点数可能由 2、3 或 4 个字节组成,但是你只需要担心 2 字节 (16 位) 的类型。前 10 位是尾数,最后 6 位是指数。
就像十进制浮点数表示一样,二进制浮点数也会有尾数和指数,但由于你正在处理二进制(以 2 为基数),你必须记住,你必须使用 而不是 .
定点二进制允许计算机保存小数部分,但由于其性质,其范围非常有限。即使使用 4 个字节来保存每个数字,并将小数点后的分数部分用 8 位表示,所能保存的最大数字也略大于 800 万。为了保存非常大的数字,需要另一种格式。
在十进制中,可以用尾数和指数来表示非常大的数字。例如 0.12²。这里 0.12 是尾数,² 是指数。尾数保存主要数字,指数定义小数点应该放置的位置。
相同的技术可以用于二进制数。例如,可以将两个字节分成 10 位用于尾数,剩余 6 位用于指数。这样可以使数字的范围更大。
在处理二进制浮点数时,需要进行几个步骤。事实上,这就像一个迪斯科舞曲套路 - 在本页面上被称为 Noorgat 舞蹈,Kemp 变奏曲(但你不会被测试名字,但它应该有助于你记住)
- 符号 - 找出尾数的符号(记下它)
- 滑动 - 找出指数的值,以及它是正数还是负数
- 反弹 - 根据指数要求,移动小数点,对于负指数,向左移动,对于正指数,向右移动
- 翻转 - 如果尾数为负数,则对其进行二进制补码操作
- 游泳 - 从小数点开始,计算尾数的值。现在确保你参考了你在符号步骤中记录的符号。
让我们试一试。我们给出了以下 16 位浮点数,其中 10 位用于尾数,6 位用于指数。记住小数点在第一个和第二个最重要位的之间
我们需要执行的第一个操作是符号,找出指数的符号
It is 0 so the mantissa is positive
Noorgat 舞蹈的第二步是滑动,我们需要找出指数的值,也就是数字的最后 6 位
So we know that the exponent is of size positive one and we will have to move the decimal point
one place to the right.
Noorgat 舞蹈的第三步是反弹,也就是将尾数的小数点移动到滑动指定的位数,这里向右移动一位。就像这样
第四步是可选的翻转。检查符号阶段,看看尾数是否为负数。不是吗?哦,好吧,你可以跳过这一步,因为我们只在尾数为负数时才翻转数字。
第五步也是最后一步是游泳。单独取尾数,我们现在可以计算出浮点数的值。从中间开始,将左侧的每个数字标记为 等等。右侧的每个数字 等等。
Voila! the answer is 1
规范化数字
[edit | edit source]在处理二进制浮点数时,你必须确保前两位不同。也就是说
绝对不是
这是因为我们必须确保我们使用的空间以最高效的方式使用。例如,如果我们取一个十进制浮点数,例如
(Planck's constant)
如果我们把它改写为
(Planck's constant)
那么你可以看到,表示法多占了 2 个字符,这两个额外的 0,尽管它代表的是完全相同的数字。当你不用担心一个数字占用多少字符时,这可能是可以接受的,但在二进制和计算机中,数字占用的空间非常重要,我们需要尽可能高效的表示法。对于固定数量的位,规范化的数字表示将以尽可能高的精度显示数字。你必须确保你的规范化不会改变尾数的符号。取一个二进制浮点数
我们可以看到这个数字以开头。为了将其规范化,我们需要将其更改为。为此,我们需要将小数点向右移动一位,并为了保留非规范化数字所代表的相同数字,我们需要相应地更改指数。当我们向右移动一位来规范化数字时,我们需要将指数更改为向左移动一位以进行补偿。因此,从当前指数中减去一。
要确保你已正确规范化,请检查
让我们尝试一个更复杂的例子
为了使尾数规范化,我们需要将小数点向右移动两位。为了保持与原始浮点数相同的值,我们需要将指数调整为减小两位。
现在检查新的规范化值是否与原始值相同。