32 位计算机只能存储最大为 2 31 - 1 的有符号整数。
这就是为什么我们的 IPv4 地址已经用完,并且进入了 64 位时代。
但是,2 31 - 1(2,147,483,647)这个数字并不比 1 万亿(1,000,000,000,000)这个数字大,而我的机器似乎可以正常显示这个数字而不会崩溃。
有人能解释一下这是为什么吗?
答案1
我通过问你另一个问题来回答你的问题:
怎样用手指数到 6?
您可能用一只手数到最大可能的数字,然后当您的手指不够用时,您就换另一只手。计算机做同样的事情,如果它们需要表示大于单个寄存器可以容纳的值,它们将使用多个 32 位块来处理数据。
答案2
您说得对,32 位整数不能容纳大于 2^32-1 的值。但是,这个 32 位整数的值和它在屏幕上的显示方式是完全不同的两件事。打印的字符串“10000000000000”在内存中不是用 32 位整数表示的。
要逐字显示数字“10000000000000”,需要 13 个字节的内存。每个字节最多可容纳 255 个值。它们都无法容纳整个数值,但单独解释为 ASCII 字符(例如,字符 ' 0
' 用十进制值 48 表示,二进制值00110000
),它们可以串在一起形成一种对您(人类)有意义的格式。
编程中的一个相关概念是类型转换,这就是计算机解释特定0
s 和1
s 流的方式。如上例所示,它可以被解释为数值、字符,甚至是完全不同的东西。虽然 32 位整数可能无法容纳 10000000000000 的值,但 32 位浮点数却可以,使用完全不同的解释。
至于计算机内部如何处理大数,存在 64 位整数(可容纳高达 160 亿亿的值)、浮点值,以及可以处理任意大数的专门库。
答案3
首先,32 位计算机可以存储最多 2 32 -1 的数字在一个机器词中。机器词是 CPU 可以以自然方式处理的数据量(即,对该大小的数据的操作由硬件实现,并且通常执行速度最快)。32 位 CPU 使用由 32 位组成的字,因此它们可以存储从 0 到 2 32 -1的数字总而言之。
第二,1万亿和1000000000000是两码事。
- 1万亿是一个抽象的数字概念
- 1000000000000 是文本
通过按1一次然后按012 次,您便可以输入文本。1输入1
,0输入0
。看到了吗?您输入的是字符。字符不是数字。打字机根本没有 CPU 或内存,但它们可以很好地处理这些“数字”,因为它只是文本。
证明1000000000000不是数字,而是文本:它可以表示 1 万亿(十进制)、4096(二进制)或 281474976710656(十六进制)。在不同系统中,它的含义更多。1000000000000是一个数字,存储这个数字又是另一回事(我们稍后会回顾这个问题)。
为了存储文本(在编程中称为细绳)1000000000000您需要 14 个字节(每个字符一个字节,加上终止 NULL 字节,基本上意味着“字符串在这里结束”)。这是 4 个机器字。3 个半就足够了,但正如我所说,对机器字的操作是最快的。让我们假设ASCII用于文本编码,因此在内存中它将如下所示:(将和对应的 ASCII 码转换0
为1
二进制,每个单词占一行)
00110001 00110000 00110000 00110000
00110000 00110000 00110000 00110000
00110000 00110000 00110000 00110000
00110000 00000000 00000000 00000000
一个单词中可以容纳四个字符,其余字符将移至下一个单词。其余字符将移至下一个单词,直到所有内容(包括第一个 NULL 字节)都适合为止。
现在,回到存储数字的问题。它的工作方式与溢出文本一样,但它们是从右到左排列的。这听起来可能很复杂,所以这里有一个例子。为了简单起见,我们假设:
- 我们想象中的计算机使用十进制而不是二进制
- 一个字节可以保存数字
0..9
- 一个字由两个字节组成
这是一个空的 2 字记忆:
0 0
0 0
让我们存储数字 4:
0 4
0 0
现在让我们加 9:
1 3
0 0
请注意,两个操作数都可以放在一个字节中,但结果却不行。不过我们还有另一个可以使用。现在让我们存储 99:
9 9
0 0
再次,我们使用第二个字节来存储数字。让我们加 1:
0 0
0 0
哎呀...这叫整数溢出并且有时会导致许多严重的问题,非常昂贵的。
但如果我们预计会发生溢出,我们可以这样做:
0 0
9 9
现在加 1:
0 1
0 0
如果删除字节分隔空格和换行符,它会变得更加清晰:
0099 | +1
0100
我们已经预测到可能会发生溢出,我们可能需要额外的内存。以这种方式处理数字的速度不如处理单个字中的数字快,而且必须用软件来实现。为 32 位 CPU 添加对两个 32 位字数的支持实际上使其成为 64 位 CPU(现在它可以原生地对 64 位数字进行操作,对吧?)。
我上面描述的所有内容也适用于具有 8 位字节和 4 字节字的二进制内存,它的工作方式几乎相同:
00000000 00000000 00000000 00000000 11111111 11111111 11111111 11111111 | +1
00000000 00000000 00000000 00000001 00000000 00000000 00000000 00000000
不过,将这些数字转换为十进制系统是比较棘手的。(但它十六进制效果很好)
答案4
关键在于理解计算机如何编码数字。
确实,如果计算机坚持使用单个字(32 位系统上为 4 个字节)的简单二进制表示来存储数字,那么 32 位计算机最多只能存储 2^32 个数字。但还有很多其他方法可以对数字进行编码,具体取决于您想要用它们实现什么目的。
一个例子是计算机如何存储浮点数。计算机可以使用各种不同的方法来对它们进行编码。标准IEEE 754定义对大于 2^32 的数字进行编码的规则。粗略地说,计算机可以通过将 32 位划分为不同的部分来实现这一点,这些部分代表数字的某些数字,而其他位代表尺寸数(即指数,10^x)。这允许更大的范围大小方面,但精度有所降低(这在许多情况下是可以接受的)。当然,计算机也可以使用多个字进行这种编码,从而提高可用编码数字的精度。IEEE 标准的简单十进制 32 版本允许精度约为 7 位小数的数字和精度高达 10^96 的数字。
但是,如果您需要额外的精度,还有许多其他选择。显然,您可以在编码中使用更多单词而不受限制(尽管在转换为编码格式和从编码格式转换为其他格式时性能会受到影响)。如果您想探索一种可以做到这一点的方法,那么有一个很棒的 Excel 开源插件,它使用一种允许在计算中使用数百位精度的编码方案。该插件称为 Xnumbers,可用这里。代码采用 Visual Basic 编写,虽然速度不是最快的,但其优点是易于理解和修改。这是了解计算机如何实现较长数字编码的好方法。而且,您可以在 Excel 中处理结果,而无需安装任何编程工具。