32位计算机最多只能存储带符号的整数231-1。
这就是为什么我们用完IPv4地址并进入64位时代的原因。

但是,数字231-1(2,147,483,647)并不比数字1万亿(1,000,000,000,000)大,我似乎可以很好地显示该数字而不会导致机器崩溃。

有人可以解释为什么吗?

评论

这个问题是有缺陷的。 32位计算机可以处理比2 ^ 32大得多的数字。他们一直在做,用“长”等。它们最多只能在一个寄存器中存储2 ^ 32,但是编写软件来绕过此问题。一些现代语言甚至没有给定数字长度的问题。

请保持话题性,礼貌性和与问题的技术方面相关的评论。已经有将近50个笑话评论已被删除,我们希望避免锁定帖子。谢谢。

这个问题写得有点草率。 “写”和“显示”数字1000000000000是什么意思?我想,当您写问题时,您写的数字是1000000000000,并且您的网络浏览器可以很好地显示它,但是对于以前使用过计算机的任何人来说,这都不奇怪。该问题要求免费翻译。

据估计,人类意识大约持有50位(我在某处读取)。因此问题不是“如何在PC不崩溃的情况下写1​​0 ^ 9?”而是“如何在不使大脑崩溃的情况下写1​​0 ^(18)?”

32位计算机最多只能存储2 ^ 32-1的UNSIGNED整数。2 ^ 32-1甚至不等于2,147,483,647 ... 300票,没有人意识到吗?

#1 楼




我通过问另一个问题来回答您的问题:


您如何指望6?


您可能会用一只手最多数,然后在手指用尽时继续使用第二只手。计算机做同样的事情,如果它们需要表示一个大于单个寄存器可以容纳的值,则它们将使用多个32位块来处理数据。

评论


好笑,@代号。那您如何指望手指达到32或更多(即2 ^ 5用尽一次)? ;)举个例子,就是举个例子,即使二进制延迟了换另一只手的需要。我想看到的是,随着脚手灵巧,可以计数到1,024或更多,以便进一步用二进制数进行计数-多达1,048,575! :)这可能是20位子板电源。 :P

– J0e3gan
2014年1月10日16:17



请保持话题性,并与讨论此答案的技术方面相关。此答案已删除了60多个笑话评论,我们希望避免锁定帖子。

–nhinkle
2014年1月11日在22:03



@ codename-容易,您可以将一个手指分配为堆栈指针。一旦手指用完,就将金额添加到堆栈中并重新开始计数。

–马卡奇
2014年1月16日上午10:37

@codename是您在哪里学到的?我首先是从Frederik Pohl那里听到的,例如在这里hjkeen.net/halqn/f_pohl3.htm

–赞恩
2014年1月17日15:15

我认为这不是有关问题的答案。 @ Bigbio2002的回答是正确的。这里的“ 1000000000000”不是数字而是文本,就像“ adsfjhekgnoregrebgoregnkevnregj”一样。您的发言是对的,但我强烈认为这不是正确的答案。看到这么多的投票...

–院长
2014年1月18日在4:40

#2 楼

您是正确的32位整数不能包含大于2 ^ 32-1的值。但是,此32位整数的值以及它在屏幕上的显示方式是完全不同的两件事。打印的字符串“ 1000000000000”在内存中没有由32位整数表示。

要从字面上显示数字“ 1000000000000”,需要13个字节的内存。每个单独的字节最多可以保存255个值。它们都不能保存整个数字值,但可以分别解释为ASCII字符(例如,字符'0'由十进制值48表示,二进制值00110000),它们可以串在一起,成为对您来说有意义的格式。和0 s。如以上示例所示,它可以解释为数值,字符或什至完全是其他内容。虽然32位整数可能无法保存1000000000000的值,但使用完全不同的解释,32位浮点数将可以。

关于计算机如何工作在内部处理并处理大量数字时,存在64位整数(最多可容纳160亿个值),浮点值以及可以处理任意大数的专用库。

评论


实际上,这大部分是正确的,但并非完全正确。一个32点浮点数不太可能能够准确地表示1000000000000。它将表示一个非常非常接近所需数字的数字,但并不完全是它。

– Tim B
2014年1月9日在10:54



@TimB:您听说过decimal32格式吗?它是IEEE 754-2008标准的一部分。此格式可以正确表示此数字:)

– V-X
2014年1月9日在12:54

是的,那可以。但是,这不是人们所说的“ float”时所指的格式,通常是指当前计算机中标准浮点处理器存储和使用的32位浮点数。

– Tim B
2014年1月9日下午13:06

@TimB确实。与可以表示为float32的数字最接近的数字是999999995904

– greggo
2014年1月9日在18:03

@TimB:但是一个64位浮点数可以很容易地精确表示1000000000000。是10 ^ 12或2 ^ 12 * 5 ^ 12; 5 ^ 12需要28位尾数。

–基思·汤普森(Keith Thompson)
2014年1月11日在19:54

#3 楼

首先,最重要的是,32位计算机在单个机器字中最多可以存储2³²-1的数字。机器字是CPU可以自然处理的数据量(即,对这种大小的数据的操作是在硬件中实现的,通常执行速度最快)。 32位CPU使用由32位组成的字,因此它们可以在一个字中存储0到2³²-1的数字。第二,1万亿和1000000000000是两个不同的东西。 br />
1万亿是数字的抽象概念
1000000000000是文本

先按1再按0 12键入文本。 1个输入1,0个输入0。看到?您正在输入字符。字符不是数字。打字机根本没有CPU或内存,它们能够很好地处理这样的“数字”,因为它只是文本。

证明1000000000000不是数字,而是文本:它可以表示1万亿( (以十进制表示),4096(以二进制表示)或281474976710656(以十六进制表示)。在不同的系统中它具有更多的含义。 1000000000000的含义是一个数字,存储它是一个不同的故事(我们稍后会再讲)。

要存储文本(在编程中称为字符串)1000000000000,您需要14个字节(每个字符一个,再加上一个终止NULL字节,该字节基本上意味着“字符串在此结束”)。那是4个机器单词。 3和一半就足够了,但是正如我所说,对机器字的操作最快。假设ASCII用于文本存储,那么在内存中将如下所示:(将与01对应的ASCII代码转换为二进制,每个单词在单独的行中)

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


将此类数字转换为但是,十进制很棘手。 (但十六进制效果很好)

评论


您的答案读得非常高。 OP显然是在谈论数字,而不是文字:数字为1万亿(1000000000000)。另外,您几乎在谈论任意精度算术,但您从未真正提及您所说的任何术语。

–MirroredFate
2014年1月8日,下午1:22

“ 1万亿”也是一个字符串

– Elzo Valugi
2014年1月8日在9:46

@ElzoValugi是的。我必须找到某种方式来表示抽象数字的概念,而不是代表数字的字符串。我相信“ 1万亿”是一种更好且不太模糊的方法(请参见答案)。

–gronostaj
2014年1月8日在11:09

@MirroredFate我不同意“显然是在谈论数字”。 OP说“显示良好”,这显然是在跟我说文本“ 1000000000000” ...

–乔
2014年1月8日在20:49

@yannbane'A'是一个字符,而不是数字。 '?'是字符而不是数字。 “ 1”是一个字符,而不是数字。字符只是符号。它们可以代表数字或数字,但绝对不是数字。 “ 1”可以代表一,十,十万,一千,依此类推,它只是一个代表数字的符号,可以是数字或数字的一部分。 “ 10”(字符串)可以表示两个或八个或十个或十六个等。但是当您说有十个苹果时,您使用的数字为十,每个人都知道您的意思。字符和数字之间存在巨大差异。

–gronostaj
2014年1月9日15:52

#4 楼

您还可以编写“此声明为假”而不会导致计算机崩溃:) @Scott的答案在某些计算框架上是正确的,但是您对“编写”的问题很多意味着它只是纯文本,至少直到它被解释。

编辑:现在,讽刺性降低了,以各种方式可以将更多有用的信息存储在内存中。我将以更高的抽象度来描述它们,即现代程序员可能在将代码转换为机器代码以执行之前先编写代码。

计算机上的数据必须限制为某种类型和这种类型的计算机定义描述了可以对此数据执行哪些操作以及如何执行操作(即比较数字,连接文本或对布尔值进行XOR)。您不能简单地将文本添加到数字中,就像不能将数字乘以文本一样,以便其中一些值可以在类型之间转换。

让我们从无符号整数开始。在这些值类型中,所有位都用于存储有关数字的信息。您的示例是一个32位无符号整数的示例,可以存储从02^32-1的任何值。是的,根据所使用平台的语言或体系结构,您可以使用16位整数或256位整数。

如果要取负数该怎么办?直观上,带符号的整数是游戏的名称。惯例是分配从-2^(n-1)2^(n-1)-1的所有值-这样,我们避免了不得不处理两种写+0-0的困惑。因此,一个32位带符号整数将保存从-21474836482147483647的值。很整洁,不是吗?

好的,我们已经介绍了整数,即不带小数部分的数字。表达这些信息比较棘手:非整数部分只能合理地位于01之间,因此用于描述它的每多一个位都会提高其精度:1 / 2、1 / 4、1 / 8 ...问题是,您不能精确地将简单的十进制0.1表示为分母中只能有2的幂的分数的和!将数字存储为整数会更容易,但是同意将基数(小数点)放在小数点会更容易吗?这称为定点数,我们在其中存储1234100,但同意将其读为1234.100的约定。

用于计算的相对较常见的类型是floating point。它的工作方式确实很整洁,它用一位存储符号值,然后用一点存储指数和有效位数。有定义这种分配的标准,但是对于32位浮点数,您可以存储的最大数量是压倒性的。但是,这是有代价的的精度。浏览器中可用的JavaScript使用64位浮点数,但仍然无法解决问题。只需将其复制到地址栏中,然后按Enter。剧透警报:结果不会是0.3

(2 - 2^-23) * 2^(2^7 - 1) ≈ 3.4 * 10^38


还有更多替代类型,例如Microsoft .NET 4.5的BigInteger,理论上没有上限或下限范围,必须以“批次”计算;但是也许更引人入胜的技术是那些了解数学的技术,例如Wolfram Mathematica引擎,它可以精确地与无穷大等抽象值配合使用。

评论


您可以在现实中做到这一点。尝试在《星际迷航》宇宙中做到这一点。因为所有的火花和烟雾,只是退后一步。

–迈克尔·彼得罗塔(Michael Petrotta)
2014年1月8日,1:17

这不完全是定点工作的方式。实际上,这是一个对数字进行缩放和偏置以产生小数点的系统。在您的示例中,比例为1/1000,但也有如下定点数(尤其是在计算机图形学中):0 = 0.0、255 = 1.0-比例为1/255。

–安东·科尔曼(Andon M. Coleman)
2014年1月10日19:26

#5 楼

关键是要了解计算机如何编码数字。

正确,如果计算机坚持使用单个单词(在32位系统上为4字节)使用数字的简单二进制表示形式存储数字,那么32位计算机最多只能存储2 ^ 32的数字。但是,还有许多其他方式可以对数字进行编码,具体取决于您要使用数字来实现。

一个示例是计算机如何存储浮点数。计算机可以使用多种不同的方式对它们进行编码。标准IEEE 754定义了对大于2 ^ 32的数字进行编码的规则。粗略地讲,计算机可以通过将32位划分为代表数字的一些数字的不同部分和代表数字的大小(即指数10 ^ x)的其他位来实现这一点。从大小上讲,这允许更大范围的数字,但是会降低精度(在很多情况下都可以)。当然,计算机也可以使用一个以上的单词进行此编码,从而提高了可用编码数字的大小的精度。 IEEE标准的简单十进制32版本允许数字的精度为大约7个十进制数字,并且数字的幅度最大为10 ^ 96。

但是如果您需要更高的精度,还有许多其他选择。 。显然,您可以无限制地在编码中使用更多单词(尽管会影响性能的转换和转换为编码格式)。如果您想探索一种方法,可以使用Excel的一个很棒的开源插件,该插件使用一种编码方案,允许数百位的计算精度。该加载项称为Xnumbers,可在此处获得。该代码在Visual Basic中不是最快的方法,但是具有易于理解和修改的优点。这是学习计算机如何实现较长数字编码的好方法。而且您可以在Excel中试用结果,而无需安装任何编程工具。

#6 楼

一切都在您的问题中。

您可以在纸上写下任何您喜欢的数字。尝试在白纸上写上万亿点。它缓慢且无效。这就是为什么我们有一个10位数字的系统来表示这些大数字。我们甚至还使用了“百万”,“万亿”之类的大数字,因此您不必大声说出one one one one one one one one one one one...

32位处理器旨在与块一起最快速有效地工作。正好是32位二进制数的内存。但是我们人们通常使用10位数字系统,而计算机是电子设备,则使用2位系统(二进制)。数字32和64恰好是2的幂。因此,百万和1万亿就是10的幂。例如,与许多65536相比,使用这些数字进行操作更容易。

我们当我们在纸上书写时,将大数字分解为数字。计算机将数字分解为更多的数字。我们可以写下我们喜欢的任何数字,如果我们这样设计的话,计算机也可以写下。

#7 楼

32位和64位是指存储器地址。您的计算机内存就像邮局的邮箱,每个邮箱都有不同的地址。 CPU(中央处理单元)使用这些地址来寻址RAM(随机存取存储器)上的存储器位置。当CPU只能处理16位地址时,您只能使用32mb的RAM(当时看起来很大)。使用32bit时达到了4 + gb(在当时似乎很大)。现在我们有了64位地址,RAM达到了TB(看起来非常大)。
但是,程序能够为存储数字和文本之类的东西分配多个内存块,这取决于程序,并且与每个地址的大小无关。因此,程序可以告诉CPU,我将使用10个地址块进行存储,然后存储非常大的数字或10个字母字符串或其他内容。
旁注:内存地址由“指针”指向,因此32位和64位值表示用于访问内存的指针的大小。

评论


除细节外,答案都很好-16位地址空间为您提供了64kb,而不是32mb,而像286这样的机器具有24位地址(为16mb)。同样,使用64位地址,您将远远超过TB-更像是16 EB-TB大约是当前一代主板/ CPU所施加的限制-而不是地址的大小。

–菲尔
2014年1月8日在7:58

32位是指机器字的大小,而不是内存地址。正如Phil所提到的,286是16位CPU,但使用24位通过内存分段进行寻址。 x86 CPU是32位,但使用36位寻址。请参阅PAE。

–gronostaj
2014年1月8日在8:30

@gronostaj井x86具有从386到Pentium的32位寻址。

–俄罗斯
2014年1月8日在9:17



支持,因为这是这里唯一的正确答案-32位是指32位存储器寻址,而不是32位算术。

–user1207217
2014年1月8日15:42

@ user1207217:??那么根据您的推理,例如Z80或8080是16位处理器(因为16位内存寻址和内存总线)?

– pabouk
2014年1月8日在22:21



#8 楼

因为显示数字是使用单个字符而不是整数完成的。数字中的每个数字都用单独的字符文字表示,其整数值由所使用的编码定义,例如'a'用ascii值97表示,而'1'49表示。在此处检查ascii表。
用于显示'a'和'1'是相同的。它们是字符文字,而不是整数。在32位平台中,每个字符文字的最大值为255,以8位或1字节大小存储该值(这取决于平台,但是8位是最常见的字符大小),因此可以将它们分组在一起并可以显示。它们可以显示多少个单独的字符取决于您的RAM。如果您只有1个字节的RAM,那么您只能显示一个字符,如果您有1GB的RAM,则可以很好地显示1024 * 1024 * 1024个字符(太懒了进行数学运算)。

但是,此限制适用于计算,但是我想您对IPV4标准感兴趣。尽管它与计算机的bit-size并不完全相关,但以某种方式影响了标准。创建IPV4标准时,他们将ip值存储为32位整数。现在,一旦您确定了尺寸,它便成为标准尺寸。我们对互联网的了解都依赖于此,然后我们用光了IP地址来分配。因此,如果将IP标准修改为具有64位,则所有功能都将停止工作,包括您的路由器(我认为这是正确的)和其他网络设备。因此,必须创建一个新标准,只需将32位整数与128位整数交换即可。并调整其余标准。硬件制造商只需要声明他们支持这一新标准,它就会大受欢迎。虽然不是那么简单,但是我想您已经明白了。

免责声明:这里提到的大多数观点都符合我的假设。为了简化起见,我可能错过了要点。我对数字不好,所以一定错过了一些数字,但是我的意思是要回答OP为何不会使PC崩溃的答案。

评论


我没有投票,但是您的答案有很多问题。 1是ASCII中的0x31,不是0x1。 1 GB = 1024 ^ 3B。在引入32位CPU之前发明了IPv4,因此说地址以32位整数存储是与OP的问题相冲突的。最后,IPv6使用的是128位地址,而不是64位。

–gronostaj
2014年1月8日在7:37

#9 楼

在处理器中,有“单词”。
有不同的单词。人们说“ 32位处理器”时,主要指的是“存储器总线宽度”。该词由不同的“字段”组成,这些字段是指与传输(24位)和控制(其他位)相对应的计算机子系统。我可能对确切的数字有误,请通过手册进行确认。

完全不同的方面是计算。 SSE和MMX指令集可以存储长整数。不影响生产效率的最大长度取决于当前的SSE版本,但始终约为64位的整数倍。 )。

摘要:(1)总线宽度未直接与计算宽度相连,(2)即使是不同的字(内存字,寄存器字,总线字等)也未相互连接,其他那么它们的公约数大约为8或16或24。许多处理器甚至使用6位字(但它的历史记录)。

评论


并非如此,原始的Pentium处理器即使是32位处理器,也具有用于高内存带宽的64位数据总线。 8088是带有8位数据总线的16位处理器。

– Doug65536
2014年1月11日23:21



#10 楼

通常,计算设备的目的是接受,处理,存储和发出数据。底层硬件仅仅是帮助执行这四个功能的机器。如果没有软件,它什么也做不了。

软件是告诉机器如何接受数据,如何处理数据,如何存储数据以及如何将其提供给他人的代码。 />
底层硬件将始终具有局限性。对于32位计算机,处理数据的大多数寄存器只有32位宽。但是,这并不意味着机器不能处理2 ^ 32以上的数字,这意味着如果要处理更大的数字,则机器可能需要一个以上的周期来接受,处理和存储该数字。

软件会告诉机器如何处理数字。如果该软件旨在处理大数,则它将向CPU发送一系列指令,告诉其如何处理大数。例如,您的数字可以由两个32位寄存器表示。如果您想在数字上加1,234,软件会告诉CPU首先在低位寄存器上加1,234,然后检查溢出位以查看该加法是否导致该数字对于低位寄存器而言太大。如果是的话,则将1加到上位寄存器。寄存器。对于大多数通用数学运算,对于任何实际大小的数字,都是如此。

#11 楼

区别在于我们如何在计算机中存储数据。

您是正确的,对于理论上的8位计算机,我们只能在单个处理器寄存器或内存地址中存储2 ^ 8值。 (请记住,根据所使用的处理器,内存体系结构等的不同,“机器”会有所不同。但是,现在,让我们继续使用假设的“定型”机器。)从理论上讲16位机器,寄存器/内存位置的最大值为2 ^ 16,对于32位机器,最大值为2 ^ 32,等等。

多年来,程序员已经设计出所有种类繁多的存储和处理数量大于存储在单个处理器寄存器或内存地址中的数量。存在许多方法,但是它们都涉及使用多个寄存器/内存地址来存储大于其“本机”寄存器/内存位置宽度的值。所有这些方法的好处在于,计算机可以存储/处理的值大于其本机容量。缺点是几乎所有方法都需要多个机器指令/读取/等。处理这些数字。对于偶尔出现的大量用户,这不是问题。当处理大量大量数据(尤其是大内存地址)时,所涉及的开销会减慢速度。

因此,人们普遍希望将寄存器,内存位置和内存地址硬件“变宽”并变宽

由于数字大小是无限的,因此处理器寄存器/内存大小/寻址始终是本机数字大小和实施越来越大的宽度所涉及的成本。

#12 楼

32位计算机在一个机器字中最多只能存储2 ^ 32的数字,但这并不意味着它们不能处理更大的数据实体。

32位计算机的含义通常,数据总线和地址总线为32位宽,这意味着计算机可以一次处理4 GB的内存地址空间,并一次通过数据总线发送四个字节的数据。 />但这并不会限制计算机处理更多数据,它只需要在通过数据总线发送数据时将数据分成四个字节即可。

常规的Intel 32位处理器可以在内部处理128位数字,这将使您可以毫无问题地处理类似100000000000000000000000000000000000000000000的数字。

您可以处理比计算机大得多的数字,但是计算必须由软件完成, CPU没有处理大于128位数字的指令。 (它可以处理浮点数形式的大得多的数字,但那时您只有15位精度。)

#13 楼

只需在其他许多答案中添加注释,因为这是该问题中一个非常重要的事实,已经被遗漏了。

“ 32位”是指内存地址宽度。它与寄存器大小无关。许多32位CPU可能具有64位甚至128位寄存器。特别是对于x86产品线,最近的全都是64位的消费类CPU拥有多达256位的特殊用途寄存器。在古代,当我们有4位寄存器和8位地址时,反之亦然。

很容易看出,不管寄存器大小如何,存储大量数字都没有问题,如其他答案所述。

之所以寄存器的大小可能恰好也可以大一些,原因是太大的计算可以分解为几个较小的计算,而这些较小的计算确实适合寄存器(实际上只是稍微复杂一点)。

评论


这不是真的。 64位指的是不一致的,但是寄存器宽度为64位的系统通常称为64位。维基百科说:“ 64位计算机体系结构通常具有64位宽的整数和寻址寄存器”。是的,现代的x86(或AMD-64)产品线具有庞大的专用寄存器,但它们具有64位主寄存器,并且可以访问48-52位的内存。较早的x86系统具有32位主寄存器并可以访问24-36位存储器,而8086被称为16位芯片,具有16位宽的寄存器并可以访问20位存储器。

– prosfilaes
2014年1月18日,12:40

@prosfilaes这是很多有价值的信息,我指的是这些信息(我和您一样都忘记了细节)。随时将其编辑为答案。

–马夫
2014年1月19日20:41

#14 楼

已经给出的答案实际上是很好的,但是它们倾向于从不同角度解决问题,因此呈现出不完整的图景。在我看来,它们也有点技术性。

因此,仅是为了阐明某些其他答案中暗示但未明确表达的内容,我认为这是关键所在。事情:

您在问题中混淆了几个概念,其中一个(“ 32位”)实际上可以指代各种不同的事物(并且不同的答案采用不同的解释)。这些概念都与在各种计算上下文中使用(或可用)的位数(1和0)有关(我的意思是希望通过下面的示例阐明这些位数),但是这些概念在其他方面是不相关的。 br />
明确地:


“ IPv4 / 6”是指Internet协议,这是一组定义如何在Internet上打包和解释信息的规则。 IPv4和IPv6之间的主要区别(至少是最著名的区别)是IPv6中的地址空间(即可以用来区分网络上不同位置的地址集)更大。这与在网络上发送的每个数据包中的多少位分配给(即留出目的)标识该包的发送方和预期的接收方有关。


-计算类比:每个数据包就像通过蜗牛邮件发送的一封信,地址空间就像您在信封上写地址和回信地址时“允许”使用的字符数。
到目前为止,我在其他任何答案中都没有提到这一点。


通常可以将计算机内存“字”(32位和64位)视为计算机使用或“思考”的最小数据。这些数据位组合在一起构成其他数据位,例如文本块或较大的整数。


非计算类比:单词可以被认为有点像在纸上组成单词的字母,甚至可以看作是思路中的单个单词。


32位指针可能是单词,也可能不是单词,但是它们还是经过原子处理的(即,不能分解成较小组件的单个单元)。指针是计算机可以在内存中记录一些任意数据块位置的最低级别的方法。请注意,计算机(或者实际上是操作系统)使用的指针大小限制了单个指针可以访问的内存范围,因为指针可以“指向”尽可能多的内存位置因为指针本身有可能的值。这类似于IPv4限制可能的Internet地址范围的方式,但不限制可以在例如特定网页中显示的数据量。但是,指针大小并不限制指针可以指向的数据本身的大小。 (有关允许数据大小超出指针范围的方案的示例,请查看Linux的inode指针结构。请注意,“指针”一词的用法与典型用法略有不同,因为指针通常是指指向的指针。随机存取存储器,而不是硬盘空间。)


非计算类比:嗯……这有点棘手。也许用于索引库资料的Dewey十进制系统有点相似?还是真的有任何索引系统。
请参阅SiteNook的答案。
请注意,我对上述指针的解释掩盖了一些细微的细节,并且可能并不完全正确。但是,在程序员直接使用指针工作的编程语言中,我绘制的思维模式通常足以满足实际目的。


(出于实际目的)计算机“可以显示”的编号不受计算机硬件或操作系统的限制;它们像其他任何文本一样被对待。


非计算类比:写在纸上
请参见user1306322的答案和Bigbio2002的答案




请注意,这并不打算成为短语“ 32位”的完整解释列表。

额外的功劳:真正看到准系统数字和计算机内存的原始块之间的哲学区别,请阅读有关图灵机的一些知识。

评论


我认为对IPv4的引用是指出,IPv4地址的数量实际上限制为带符号的32位整数的长度,而IPv6使用128位,因此可以具有多个数量级的地址。

– Clonkex
17年7月21日在6:26

@Clonkex可能,尽管绝对不是问题所在。

–凯尔·斯特兰德(Kyle Strand)
17年7月21日在14:00

#15 楼

例如,如果在计算器中写入1000000000000,计算机会将其计算为带小数点的实型数字。您提到的32位限制会触及所有不带小数点的所有整数类型数字。不同的数据类型使用不同的方法来获取位/字节。

整数类型数字:
此表可以帮助您找到要点(http://msdn.microsoft.com/cn -us / library / 296az74e.aspx)。这触及了C ++的限制。例如,Int64类型号的范围从-922337203685477575808到9223372036854775807。

实际类型号:
实际类型号包含带浮点数和指数的值,您可以输入大得多的数字,但数量有限准确性/精度。 (http://msdn.microsoft.com/zh-cn/library/6bs3y5ya.aspx)例如,C ++中的LDBL(大双精度)的最大指数为308,因此您可以输入或得到的结果编号为9.999 x 10^308,表示您理论上将使用9的308(+1)位数字,但是仅使用15个最重要的数字来表示它,其余的将丢失,这是精度有限的原因。

另外,还有不同的编程语言,它们可能具有不同的数量限制实现。因此,您可以想象,专用应用程序可以处理比C ++大得多(和/或更精确/精确)的数字。

评论


这个“答案”是不正确的:计算器使用BCD数字表示形式以避免截断错误。即0.1十进制不能精确表示为有限长度的二进制数。

–木屑
15/12/22在8:31

#16 楼

如果您想了解一个典型的Linux系统上有多少个程序可以处理大量处理和输出的实际示例:

libgmp-GNU多精度算术库是为此目的最广泛使用的库在Linux系统上。一个简单的示例,将2 ^ 80乘以1000:

#include <gmp.h>

// Each large integer uses the mpz_t type provided by libgmp
mpz_t a_large_number;
mpz_t base;
mpz_t result;

// Initalize each variable
mpz_init(a_large_number);
mpz_init(base);
mpz_init(result);

// Assign the number 2 to the variable |base|
mpz_set_ui(base, 2);

// Raise base^80 (2^80), store the result in |a_large_number|
mpz_pow_ui(a_large_number, base, 80);

// Multiply |a_large_number| by 1000, store the result in |result|
mpz_mul_ui(result, a_large_number, 1000);

// Finally, output the result in decimal and hex notation
gmp_printf("decimal: %Zd, hex: %ZX\n", result, result);


因此,基本上与使用常规+-* /运算符相同,只是使用一个库来破坏编号并将其内部存储为多个机器字大小(即32位)的数字。还有scanf()类型的函数可用于将输入的文本转换为整数类型。

mpz_t的结构与斯科特·张伯伦(Scott Chamberlain)的用两只手计数到6的示例完全一样。它基本上是大小为mp_limb_t的机器字数组,当数字太大而不能容纳机器字时,GMP将使用多个mp_limb_t来存储数字的高/低部分。

#17 楼

在您的脑海中,您只会知道10个不同的数字。 0到9。在大脑内部,它的编码方式肯定不同于计算机。

计算机使用位对数字进行编码,但这并不重要。那只是工程师选择编码的方式,但是您应该忽略它。您可以将其想象为一台32位计算机,它具有超过40亿个不同值的唯一表示形式,而我们人类却具有10个不同值的唯一表示形式。我们使用一个系统。最左边的数字是最重要的。它比下一个要重要10倍。

能够区分40亿个不同值的计算机,同样必须使一组值中最左边的值变得重要40亿倍。作为该集中的下一个值。实际上,计算机根本不在乎。它不会为数字分配“重要性”。程序员必须编写特殊的代码来解决这一问题。

每当一个值大于唯一符号的数量(在人类头脑中为9)时,您都要在左侧的数字上加一个。

3+3=6


在这种情况下,数字仍然适合单个“插槽”

5+5=10. This situation is called an overflow.


因此,人类始终会与之打交道没有足够的唯一符号的问题。除非计算机具有用于处理此问题的系统,否则它只会写0,而忘记会有多余的数字。幸运的是,在这种情况下,计算机会出现一个“溢出标志”。

987+321 is more difficult.


您可能已经在学校学习了一种方法。一种算法。该算法非常简单。首先添加两个最左边的符号。

7+1=8, we now have ...8 as the result so far


,然后移至下一个插槽并执行相同的加法。

8+2=10, the overflow flag is raised. We now have ...08, plus overflow.


由于溢出,这意味着我们必须在下一个数字前加1。

9+3=12, and then we add one due to overflow. ...308, and we had another overflow.


没有更多可添加的数字,因此我们只创建了一个插槽和插入器1,因为溢出标志被提高了。

除了具有2 ^ 32甚至更好的2 ^ 64个不同的符号,而不是像人类一样的10个符号。

在硬件级别上,计算机使用完全相同的方法处理单个位。幸运的是,这对于程序员来说是抽象的。位只有两位数字,因为这很容易在电源线中表示。最后,要么亮起,要么熄灭。

最后,计算机可以将任何数字显示为简单的字符序列。那就是计算机最擅长的。在字符序列和内部表示之间转换的算法非常复杂。

评论


在我看来,我知道36个,但通常只使用16个。

–凯尔·斯特兰德
2014年1月13日21:00

“一台计算机使用位对数字进行编码,但这并不重要。”在用户询问大约32位字以及如何使用它们存储大于2 ^ 32-1的数字的情况下,这一点非常重要。

– RichieHH
2014年1月17日在13:26



在大脑的记忆中如何编码数字并不重要。您有数量有限的表示形式;大多数人学会了10种不同的符号。在您的大脑内部,这可能以数千个神经元和突触的形式表示。在计算机中,它以电力或电力线上无电的形式表示。从编程的角度来看-或在学习数学时,这根本不重要,除非在极少数情况下直接针对一组特定的CPU进行编程。他要的是32位和64位,而不是单个位。

– frodeborli
2014年1月17日14:04

#18 楼

因为您不是在显示数字(就计算机而言),而是显示字符串或数字序列。当然,我猜有些处理数字的应用程序(例如计算器)可以处理这样的数字。我不知道他们使用什么技巧...我敢肯定,还有其他一些更详尽的答案可以解决这个问题。

#19 楼

该答案的大部分内容最初来自此答案(在该其他问题标记为重复之前写的)。因此,我讨论了使用8位值(即使这个问题询问了32位值),但这没关系,因为从概念上更容易理解8位值,并且相同的概念适用于较大的值,例如32位算术。 br />
将两个8位数字相加时,可以获得的最大数字(0xFF + 0xFF = 1FE)。实际上,如果将两个8位数字相乘,则可以得到的最大数字(0xFF * 0xFF = 0xFE01)仍然是16位,是8位的两倍。

现在,您可以假设x位处理器只能跟踪x位。 (例如,一个8位处理器只能跟踪8位。)这是不准确的。 8位处理器以8位块的形式接收数据。 (这些“块”通常有一个正式术语:“字”。在8位处理器上,使用8位字。在64位处理器上,可以使用64位字。)

因此,当您为计算机提供3个字节时:
字节1:MUL指令
字节2:高位字节(例如0xA5)
字节3:低位字节(例如0xCB)
计算机可以生成8位以上的结果。 CPU可能会生成如下结果:
0100 0000 0100 0010 xxxx xxxx xxxx xxxx 1101 0111
又名:
0x4082xxxxD7
现在,让我为您解释一下:
0x只是表示以下数字是十六进制。
我将在稍后详细讨论“ 40”。
82是“ A”寄存器的一部分,该寄存器由8位组成。
xx和xx是另外两个寄存器的一部分,分别称为“ B”寄存器和“ C”寄存器。我没有用零或一填充这些位的原因是“ ADD”指令(发送给CPU)可能导致这些位未被该指令更改(而本例中我使用的大多数其他位可能被更改,除了一些标志位)。
D7可以容纳更多的位,称为“ D”寄存器。
寄存器只是一块内存。寄存器内置在CPU中,因此CPU无需访问RAM棒上的内存即可访问寄存器。

0xA5乘以0xCB的数学结果为0x82D7。 />现在,为什么将这些位拆分为A和D寄存器而不是A和B寄存器,或C和D寄存器?好吧,这再次是我正在使用的示例场景,其概念与真实的汇编语言(Intel x86 16位,如Intel 8080和8088以及许多较新的CPU使用)在概念上非常相似。可能存在一些通用规则,例如“ C”寄存器通常用作计数操作的索引(对于循环而言是典型的),而“ B”寄存器用于跟踪有助于指定存储位置的偏移量。因此,“ A”和“ D”在某些常见的算术函数中可能更常见。

每个CPU指令都应该具有一些文档,供汇编程序的人员使用。该文档应指定每个指令使用哪些寄存器。 (因此,使用哪个寄存器的选择通常由CPU的设计人员指定,而不是由汇编语言程序员指定。尽管有一定的灵活性。)

现在,回到上面的示例中的“ 40”:这是一系列位,通常称为“标志寄存器”。标志寄存器中的每个位都有一个名称。例如,如果结果大于可以存储结果一个字节的空间,则CPU可能会设置一个“溢出”位。 (“溢出”位通常可以用缩写名“ OF”来指代。这是大写的o,而不是零。)软件可以检查该标志的值并注意到“问题”。使用此位通常是由高级语言进行的,因此,初级程序员常常不了解如何与CPU标志进行交互。但是,汇编程序员通常可能会以与其他变量非常相似的方式访问其中一些标志。例如,您可能有多个ADD指令。一个ADD指令可能将16位结果存储在A寄存器和D寄存器中,而另一条指令可能只是将8个低位存储在A寄存器中,忽略D寄存器,并指定溢出位。然后,稍后(将A寄存器的结果存储到主RAM中之后),您可以使用另一条ADD指令,该指令仅将8个高位存储在寄存器(可能是A寄存器)中。是否需要使用溢出标志可能会

(通常还会有一个“下溢”标志,以防您减去太多而无法达到所需的结果。)

只是向您展示事情变得多么复杂:
英特尔4004是4位CPU
英特尔8008是8位CPU。它具有一个名为A,B,C和D的8位寄存器。
英特尔8086是16位CPU。它具有名为AX,BX,CX和DX的16位寄存器。
英特尔80386是32位CPU。它具有名为EAX,EBX,ECX和EDX的32位寄存器。
Intel x64 CPU具有名为RAX,RBX,RCX和RDX的64位寄存器。
x64芯片可以运行16位代码(在某些操作模式下),并可以解释16位指令。这样做时,组成AX寄存器的位是组成EAX寄存器的位的一半,也就是组成RAX寄存器的位的一半。因此,无论何时更改AX的值,也都在更改EAX和RAX,因为AX使用的那些位是RAX使用的位的一部分。 (如果将EAX更改为65,536的倍数,则低16位不变,因此AX不会更改。如果您将EAX更改为非65,536的倍数,那么也会影响AX 。)

除了我已经提到的标志和寄存器之外,还有更多的标志和寄存器。我只是选择了一些常用的示例来提供一个简单的概念示例。

现在,如果您使用的是8位CPU,则在写入内存时,您可能会发现一些限制,指的是8位地址,而不是4位或16位地址。具体细节因CPU而异,但是如果您有此类限制,则CPU可能正在处理8位字,这就是为什么CPU最常被称为“ 8位CPU”的原因。 >

评论


我觉得我的答案部分重复了这个问题的其他一些答案。但是,当我第一次编写内容时并没有注意到这一点,因为我为另一个问题编写了内容。另外,虽然我很欣赏Animism的回答,其中包括一些用C语言编写的代码,但我仍感到内容提供了一些有关Assembly如何工作的详细信息,这更接近于CPU的实际动作/设计。因此,我的答案并不是试图成为优于所有其他答案的高级答案,而只是补充性的;通过其他一些见解添加另一个观点

– TOOGAM
16 Dec 30 '11:58