为什么计算机从零开始计数?


55

传统上,计算机计算从零开始的数值。例如,基于C的编程语言中的数组从索引零开始。

造成这种情况的历史原因是什么?从零开始计数比从一开始计数有什么实际优势?

注意:此问题要求提供解释清楚的技术答案,而不仅仅是观点,并且旨在涵盖一般计算机,而不仅仅是编程。此问题扩展到程序员问题“为什么结构/数组从零开始?”



9
已经有不止几个使用1源数组的计算机语言示例。
Daniel R Hicks

23
人类为什么不从0开始计数?
无题

47
哇,哇,没有人从零开始计数,我们从零开始索引。没有人说“零”元素。我们说索引为0 的“第一个”元素。将索引视为元素与第一个位置的偏移量。好吧,第一个元素在第一个位置,因此它根本没有偏移,因此它的索引是0。第二个元素在它之前是一个元素,所以它在元素1处偏移并且在索引1
mowwwalker

14
@Ramhound不,不是。从零开始的索引与使用二进制完全无关。
彼得·奥尔森

Answers:


88

从0开始计数数组简化了每个元素的内存地址的计算。

如果将数组存储在内存中的给定位置(称为地址),则每个元素的位置可以计算为

element(n) = address + n * size_of_the_element

如果您将第一个元素视为第一个元素,则计算将变为

element(n) = address + (n-1) * size_of_the_element

差别不大,但是每次访问都会添加不必要的减法。

编辑

  • 使用数组索引作为偏移量不是必须的,而只是一种习惯。系统可以隐藏第一个元素的偏移量,并在分配和引用元素时将其考虑在内。

  • Dijkstra发表了一篇论文“为什么编号应该从零开始”(pdf),他解释了为什么从0开始是更好的选择。从零开始可以更好地表示范围。


8
+1为正确答案。请注意,基于0的索引只是所使用语言的一种(非常常见的)约定;这不是普遍的。例如,Lua使用基于1的索引。过去,“不必要的减法”可能是基于0的索引背后的原因,但是现在大多数语言使用它的原因仅仅是因为这是每个人都已经习惯的(很大程度上要感谢C),并且没有令人信服的理由更改它惯例。
BlueRaja-Danny Pflughoeft13年

2
这是没有道理的。address + n * size_of_element只要“地址”是第零个元素的地址,就可以始终计算每个元素的位置。无论第零个元素是否作为数组的元素存在,这都可以正常工作。问题是为什么第零个元素存在,而不是为什么我们将地址存储为(可能是名义上的)第零个元素的地址。(这将回答。)
David Schwartz 2013年

3
@DavidSchwartz让我们以一种古老的语言作为C。如果分配内存,您将获得一个内存开始的地址。如果编译器看到类似的东西v[n],则必须计算表达式的地址。如果索引以0开头,则计算为v + x * size。如果为1,则计算为v +(x-1)* size。例如,v [1]对应于v +(1-1)*大小,即
v。– Matteo

4
@David:在C (真正流行基于0的索引的语言)中,数组和指针在很大程度上可以互换,因此出于多种原因,它*array实际上是指第一个元素,这一点很重要。一个例子:如果我们array指向第一个元素之前的存储位置,则强制转换为其他类型的数组会很麻烦。ints 数组中第二个字节的位置将取决于字长;在32位计算机上,它将是((char*)intArray + 5)!!
BlueRaja-Danny Pflughoeft13年

3
不,这不是数组是否具有第零个元素的问题。因为您看到了,因此也有扩展。如果我有一个8个字节的对象数组,并用字节数组覆盖它,那么对象[42]的字节索引是什么?为什么这么简单:42 * 8.基于1的问题是,当我查看字节数组时,此偏移量1为1个字节,而当查看覆盖的8字节单位数组时,偏移量为8个字节。
卡兹(Kaz)

38

尽管以下原理适用于十进制以及任何其他基数,但从表示计算机中使用的数字的固定数字二进制系统中自然可以很容易地理解计算机中从0开始计数。如果您有8位,则可以表示256个1和0的可能组合。您可以使用这些8位来表示数字1-256,但这会省略0,这在数学中本身就是一个数字,因此在数学中很有用,因此它们用于表示数字0-255。

这已经设置了自然顺序的先例,从0(二进制表示中的全0)到255(8位数字中的全1)开始。考虑到代表数字的系统,从0开始是有意义的,因为0是系统中的“第一个”数字,所以1是“第二个”数字,依此类推。

在计算机中从0开始如此方便的另一个原因是偏移量的概念。偏移量是一个数字,表示与内存或硬盘或任何其他“可寻址”介质中某个位置的距离。在计算机中,实际上所有数据都是线性存储的,这意味着该数据有一个顺序,第一个字节,第二个字节等。通过偏移量表示数据“区域”的位置很方便。数据块中的第一个字节是什么?它在偏移量“ 0”处,这意味着在数据块中第一个字节之后的0个字节处可以找到它。尽管可以将“ 1”指定为第一个字节,但是由于以下几个原因,这会在数据表示中带来麻烦:

  • 通过排除用于寻址数据的0,可以将8位数字可寻址的对象数减少一。
  • 为了计算偏移量,这是在数据访问的硬件级别上必需的,在某些时候,您必须从编号中减去一个,这会带来复杂性。
  • 指向数据块的指针始终指向第一个块,因此从0开始时算术就很简单。(即,从0开始时,第一个数据簇的第一个块中的第一个字节为0 + 0 + 0。 ,从1开始为1 + 1 + 1--1 -1。)当从1开始使用嵌套数据结构(例如本示例)时,其算法会令人困惑。

31
与二进制表示形式无关。二进制和十进制数字都从0开始
。– Matteo

2
如果从0开始计数,则不会(理论上)将地址数量从1减少到257。–
Matteo

6
@Matteo没有一个字节,您无法做到
停止危害莫妮卡(

8
@Dougvj从零开始的计数与二进制绝对无关。正在制作的点为约利用在固定位数表示的每一个数值,这是一个问题,无论是否使用基体2的,基部10,或碱23517.
彼得奥尔森

2
-1与二进制表示形式绝对无关。
BlueRaja-Danny Pflughoeft13年

26

从来没有想过超级用户会给像我这样的扶手椅哲学家带来机会。这里有一个基本的误解,因为非哲学家倾向于跳过一些细节。简而言之: 计算机不是从零开始计数,而是仓位面额从零开始。

对于计算机和人类(任何)计数技术之间的这种不一致,没有任何混淆。让我们分解问题。

为什么计算机从零开始计数?

  • 他们不从零开始计数

计算机计算从零开始的值。例如,C语言中的数组。

  • 索引(的位置指示器,讯号)从零开始。索引为零的单个元素的数组中元素的数量1

零实际上是表示某物或标尺的中点的空白。对任何事物进行计数都是不实际的,因为根据零的定义它是不可能的。

在与刻度的中点相同的意义上,零可以用来表示集合的最边缘(绝对起点)。这个问题毫无意义,因为它在“计数值”和“从零计数”之间是不一致的。

因此,是的,计算机的计数从零开始,但从一开始计数。这两个词具有不同的含义。

tal·ly [tal-ee]

名词

  1. 帐户或计算;借方和贷方记录,游戏得分等记录。
  2. 保留分数或帐户的任何内容。
  3. 记录的一组或一组项目。

[kount]

动词(与宾语一起使用)

  1. 逐一检查(集合的单独单元或组)以确定总数;加起来; 列举:他数了票,发现他有十张。
  2. 估算 计算; 计算。
  3. 列出或命名以下数字:闭上眼睛数十。

(dictionary.com)


Dougvj已充分描述了实际原因,在此我无话可说。如果我们能请一位60年代的CS教授讲一个历史的话...


实际上,您如何知道计算机在哪里启动?您所知道的是,当您使用它时,您告诉它从零开始。
Daniel R Hicks

我在这里谈论的是概念和逻辑的定义,而不是计算机本身的工作方式。我了解计算机从哪里开始的所有内容,因为我参加过CS课程。
ЯрославРахматуллин

1
要完全学究,您要将动词与名词进行比较。我认为“ tally”和“ count”确实是同义词,并且都可以用作动词或名词。
布莱恩

1
@Brian一个公平的观察,我的意图是(以一种ant腐的方式)说明这种混淆是由于对术语的误解所致。“第一个元素”和“位置0的元素”之间并没有真正的区别。它们都是元素之一。第一个,而不是“ 第零个 ”。没有从零开始计数的事情。根据定义,枚举从1开始,而寻址可能是a-> 1,b-> 2。c-> 3或0-> 1、1-> 2、2-> 3。可以从{x₀,x₁,x2}的形式在中学数学书中找到“从零开始计数”的最常见示例,但是下标是一个索引

1
只是设计师实际上在确定当前方案之前徘徊了很多时间。现在似乎不是“显而易见的”。可能已经选择了一种略有不同的方案,现在看起来比我们现有的方案“更明显”。
Daniel R Hicks

12

我觉得这已经由之前“覆盖prof.dr.艾兹赫尔·戴克斯特拉 ” - 巴勒斯研究员日期为1982年8月11日的一封信:CF EWD831

标题:为什么编号应从零开始“有理由比另一项更喜欢一个公约吗?是的,有...。”

还请注意,Dijkstra 一直待到1968年才加入ALGOL 68设计团队。Algol68允许使用0、1或程序员认为适合该算法的任何数字组成的数组。cf(“ Algol 68的制作”讲述了““您能定义三角形阵列吗?”有人(托尼·霍亚尔)打断。“不仅是三角形,甚至是椭圆形的” Aad回答,并展示了如何。

具体来说,在Algol68中,对数组(和矩阵)进行切片时,它们的索引为@ 1,因此对[1:...]数组有偏差。但是,可以通过指定“ @ 0”(例如向量x [4:99 @ 2],矩阵y [4:99 @ 1,4:99],将1st ”的下界移动到从0th位置开始@ 0]。类似地有一个默认/偏压在1 DO〜OD环(除非“ 0”明确地陈述),并从1为整数的情况下〜,〜,〜ESAC和$ C(〜,〜,〜 )$ 选择条款。

似乎Dijkstra对1968年3月的报告草稿(MR93)的评论和他的坚持激起了可以说是使用前的网络火焰战争“尽管有不合语法的地方还是有吸引力的,还有其他的文章都非常符合语法要求。我实在无法向肤浅的人解释。” EWD230

Algol 68最终报告(FR)于1968年12月20日发布,当时该报告在慕尼黑会议上遭到反感,然后被工作组通过。随后被联合国教科文组织批准的大会报告IFIP出版。

大约在1968年12月23日(?),Dijkstra,Duncan,Garwick,HoareRandell,Seegmuller,Turski,Woodger和Garwick签署了AB31.1.1.1“少数民族报告”,第7页(1970年出版)。


10

别人提出的距离比喻很实用:

“你家离最近的加油站有多远?”

“ 1英里。”

“你住在加油站吗?”

“不,如果我住在加油站,那将是0英里”

“为什么从零开始而不是从一开始计数?”

另一个很好的例子是生日-我们不是说某人的生日是一岁,而是一年之后。

我们说leap年或美国总统选举是每四年一次,即使您从以下年份算起也是如此:2000年,2001年,2002年,2003年,2004年是五年。(顺便说一句,罗马人确实把它搞砸了一段时间,并且leap年距离太近了)

我的观点是,在现实世界中,我们始终从零开始“计数”-“在[数组的开始]之后有多少个位置是您想要的元素”,恰好是您要从零开始计数的问题在许多计算机程序中。您不会说第一个元素是起点之后的一个位置,是吗?这开始。


1
您关于选举的数学关闭了一年。您的示例在5年内包含2个选举年;正确的例子是从一次选举到下次选举有4年,即2000年-> 2001年(为期1年),2001年-> 2002年,2002年-> 2003年,2003年-> 2004
。– Jimmy

1
@Jimmy这就是我的意思 -如果人们以他们想要计算机的意义“从一开始算起”,那么他们会将2000视为一而不是零。顺便说一句,这就是古罗马人实际上是如何做到的(确实可以将“ 2000、2004、2008”之类的周期描述为五年周期)。
2013年

2
你的生日例子并非普遍如此。例如,在韩国,生命的第一年被计算为一而不是零
BennyMcBenBen

6

正如其他人已经说过的,计算机不从零开始计数

某些语言从0开始索引。从0开始索引有两个主要优点:

  1. 它可以自然地转换为汇编,因为它可以解释为从指针到第一个位置的偏移量。

  2. 当你想要负面的时候,你不会变得很奇怪。从1BC到1AD多少年?没有。因为尽管BC实际上是负日期,但没有零年。如果存在0AD,那么这里就不会有任何问题。您会在整个科学领域中看到同样的问题,因为人们天真地将集合中的第一个元素定义为+1。


是的,直到2001年等待新的千年的整个愚蠢。正是这些迷惑了那些在编程时也没有“得到”基于零的数组的人。:)
Kaz

3
另外,如果“ 1英里”的意思是“就在这里”,那么由于1英里是1760英尺,所以这意味着“ 1760英尺”也就意味着“就在这里”,对吗?错误的是,“ 1英尺”就在这里,哎呀!在这其中基于愚蠢,“就在这里”是道高一尺,一寸,一厘米等
卡兹

1
@kaz脚=>码。一英里1760码。
Brad

3

自然地从零开始计数

这是计算篮子中苹果的算法:

count := 0

for each apple in basket
   count := count + 1

执行上述操作后,count保存苹果的数量。它可能为零,因为购物篮可以是空的。

如果您整个月都没有使用信用卡,您会收到1美元的账单吗?还是1美分?

当您重置汽车里程表上的行程表时,它会变为0001还是0000?

数组可以提供相同数据的多个视图

考虑由32位结构组成的数组,d每个结构由16位字组成w。每个字由两个8位字节组成b。在零索引下,覆盖看起来非常方便:

d: |   0   |   1   |
w: | 0 | 1 | 2 | 3 |
b: |0|1|2|3|4|5|6|7|

d[1]字地址处的32位对象w[2]很容易通过将索引乘以2来计算,该值是32位和16位对象的大小之比。此外,在字节寻址中为b[4]

之所以可行,是因为在每个度量单位中,零为零:字节,字,双字等。

看上图:它看起来很像标尺,单位转换很直观。

使用基于一个的索引,它会中断:

d: |   1   |   2   |
w: | 1 | 2 | 3 | 4 |
b: |1|2|3|4|5|6|7|8|

现在我们不能简单地将d索引乘以2来获得w索引,也不能简单地乘以4来获得b索引。单位之间的转换变得笨拙。例如,从d[2]b[4],我们必须计算((2 - 1) * 4) + 1 = 5

我们必须减去讨厌1的d单位偏差,然后在基于自然零位的坐标系中进行缩放,然后再将讨厌1的b单位相加。请注意,它不一样1!我们减去一个双字宽度,然后加一个字节宽度

在数据的不同视图之间进行转换就像是摄氏温度转换。

那些说基于一的数组在实现级别很容易处理的人,因为只是简单地减去1就骗了自己,而你却在自欺欺人。仅当我们不对不同数据类型进行任何缩放计算时,这才是正确的。这种计算发生在对数据具有灵活视图的任何程序(例如,也可以作为一维数组访问的多维数组)或操纵存储的程序中:例如,内存分配器,文件系统或视频帧缓冲库。

减少位数

在任何基数中,如果要使用最少的数字来实现作为基数幂的值范围,则必须从零开始。例如,以10为底的三位数足以为我们提供从0到999的一千个不同值。如果我们从1开始,我们只会溢出一个值,因此我们需要四位数。

这在计算机中很重要,因为二进制中的位数转换为硬件地址线。例如,其中有256个字的ROM芯片可以从0到255寻址,这需要8位:00000000到11111111。如果从1到256寻址,则需要9位。我们必须浪费更多的地址走线到电路板或集成电路。所以在实践中可能会发生的是,将只调用 0在用于访问该芯片的软件API级别上为1。对字1的请求实际上会将00000000放在8位地址总线上。否则,对1的请求将按预期转换为地址00000001,但对256的请求将映射到其他情况下未使用的8位地址00000000而不是9位地址100000000 。搜索问题,并且在硬件,软件以及所有用户界面和文档中始终使用0到255完全可以避免。

从一开始的流离失所从根本上是愚蠢的

以西方音乐理论为例。我们有七个音符的全音阶音阶,但我们称它们为八度音阶的空间!然后间隔的倒数遵循的规则:例如,三分之一的倒数是第六(从九中减去三)。所以三个简单的数字在起作用:七个(音阶),八个(八度音阶)和九个(减至倒数)。

如果七个音符构成一个七音阶或七音阶,并且音程是从零开始的,那么我们将从七个音符中减去以求倒数。一切都基于七个。

此外,间隔很容易堆叠。在当前系统中,如果我们先跃升五分之一,然后再跃升四分之一,然后再跃升三分之一,我们就不能仅仅添加这些。结果间隔减少了两个。它不是十二分之一,而是十分之一!在每个阶段,我们都必须减去一个。上升五分之一然后上升四分之一不是九分之一,而是八度。

在合理设计的音乐系统中,我们可以添加间隔来确定最终的跳跃。在同一音符上开始和结束的一系列音符将具有类似于电路周围的电压定律的属性:所有间隔将加为零。

音乐理论和写作已经过时了。自从用蜡烛点燃羽毛笔作曲以来,大部分内容都没有改变。

基于1的系统使那些无法处理基于0的数组的人感到困惑

当2000年到来时,许多人感到困惑,为什么新千年还没有开始。那些指出直到2001年才开始的人被认为是党的oper子和矮人。毕竟,您20岁时就已经20岁了,对吧?不是21岁时。如果您认为千年始于2000年1月1日,那么您无权抱怨任何编程语言中从零开始的数组。他们以您喜欢的方式工作。(但是,是的,一维位移和阵营的拥护者是矮人和共产党人。百年应该在XX00年开始,而千年应该在X000年开始。)

日历很傻,但是至少一天中的时间是从零开始的

手表上的每一分钟都是从:00秒开始的。每个新的小时从00:00分钟和秒开始。而且,至少在24小时制时,午夜来临的时候轮到一天了,并且11:59:59递增到00:00:00。

因此,如果您想从午夜开始计算13:53:04之类的秒数,则只需计算13 * 3600 + 53 * 60 + 4。没有平淡的1加法或减法。

关于MIDI的结束语

好的,对于音乐家,甚至是技术熟练的音乐家来说,这是什么?

MIDI!它在消息的实际有线表示中对程序和通道使用从零开始的编号,但是齿轮将其显示为从1开始!例如,大多数齿轮上的0到127程序被称为1到128,但是有些人将其称为0到127,甚至给用户一个选择。

程序71到80被认为是十个的“库”。例如,它在我的MIDI踏板上说得很对。脚踏开关标记为1到10,如果我在第七银行,它们会选择程序71到80。但是,某些设备或计算机软件会将1-128程序号显示为0到127,甚至给用户一个选择!更糟的是:基于1的系统,或同时使用基于1和0的情况造成的混乱?

MIDI通道号称为1到16,但以0到15二进制表示。似乎尽管出于基于一的表示,但某些设备还是使用了一个Dispswitch来配置通道号,并且通常,这些开关仅使用基于零的二进制代码。因此,如果要使用通道3,则必须将其切换为0010(二进制2)。


1

如果我从编程语言概念课上正确记起...语言被索引为0,其他语言被索引为1,则与历史原因有关。实际上,编程语言的祖父Algol-68,Fortran和其他一些“业务”语言(例如COBOL)都被编入了索引。但是,在其中一些语言中,您实际上可以明确指定起始索引是什么。有这样一个有趣的表在这里

基本上回到“ Ye Olde Days ”,数学家,科学家和其他“学术界”通常使用0索引语言,而使用COBOL之类的语言的用户发现从0开始计数是没有用的,因此在这些语言中更有意义从1开始(似乎不太混乱)。

现在,如果您的问题是关于为什么一台计算机不是一种语言)自然会从零开始计数的原因……那么我猜想二进制实际上是固有的:ex: 0000= 0 0001= one ...依此类推向前...


4
与二进制表示形式无关。二进制和十进制数字都从0开始(如您的示例所示)。
Matteo

好吧,它与二进制文件还有其他关系。使用0000至1111这四个位,可以寻址16个字的存储体。如果您从一开始进行操作,则需要五条地址线来表示0001到10000。否则,您将执行MIDI通道号操作:内部使用0000,但用户界面显示1!如果硬件是基于十进制的,那将是相同的问题。如果从零开始,三位数字为您提供一千个地址,但是如果您从1开始,则需要四位数字。
卡兹(Kaz)

1

数字0可以表示各种含义:数值,序数,内存地址等。

“索引零”并不意味着程序员从零开始计数。它表示已分配存储块的第一位,“ 0”是其地址。

在C语言中,遍历数组可以写成如下形式:

int arr[N];
for (i=0; arr[N]; ++i) {
...
}

可以在C#中完成相同的工作:

Object[] arr;

for (Object o in arr) {
...
}

我认为这两个例子都没有计算在内。


1

在描述与某物的距离时,从零开始是可行的。因此在此数组中:

[4,9,25,49]

从数组开始到25的距离为2-您需要跳过两个步骤才能到达那里。到4的距离为零-完全不需要从头开始。

累加距离(或索引)时,像这样思考是可行的-我先走一步,然后零步,再走两步,我在哪里?我的索引是1 + 0 + 2 =3。跳过三个步骤,我最终在上面的数组中为49。


建筑物中的楼层计数实际上应该是相同的方法(即使我们在美国没有这样做),地面高度应该为零,因为您尚未上升或下降。这是一个开始的位置。

然而,第一层是您来的。当您进入建筑物的一楼时,您便开始进行计数,并在上楼时进行添加。如果您将“在建筑物内”视为默认/正常/自然状态,则从零开始是有意义的,这对于城市社会来说是一个有趣的评论。如果多个子级别是通用的,则地面级别为零也很有意义。

1

记住数字是如何在计算机中表示的。让我们来一个byte变量。0 以二进制表示为00000000 1。1是00000001。2是00000010。依此类推。

请注意,a byte可以存储的最低数字为0。如果我们从1开始数组索引,则系统效率不高,因为我们现在拥有长度为255而不是256的数组。由于C程序中的数字会编译为二进制数(int通常是unsigned ints,通常是数组索引中的s),将0用作起始索引似乎很自然,因为它效率更高。

此外,在C ++中,a[p]展开为*(a+p*n),其中n数据类型的大小。换句话说,a[p]意思是“给我索引中的元素a+n*p”。如果以p开始1,则index处将有一个空白/未使用的部分a

1.当然,出现了一个明显的问题“为什么”。为什么不将00000000设置为1?简单:二进制加法(通过全部加法器单元的级联完成)在00000000为0时在硬件中很容易。二进制加法是所有算术运算必不可少的部分。如果使它表示为1,则可能需要告诉编译器从所有数字中减去1,或者需要对加法器电路进行硬连线,以从加数中首先减去一个,然后再将其加回到总和上。(请注意,您以后不能再减去一个,因为可能涉及进位)


@sec,因为这在硬件级别变得荒谬(请参阅编辑)
Manishearth 2013年

1

模数

现有的好答案尚未提及的一件事:基于零的索引与模运算一起很好地工作,因此可以将其组合以形成循环列表。例如考虑类似

color = colors[i % colors.length]

这可能会为每个对象(由索引i)赋予与列表不同的颜色colors,直到使用完所有颜色为止,这时它将从头开始。在基于索引的索引中表达相同的内容非常笨拙:

color = colors[(i - 1) % colors.length + 1]

固定大小的无符号二进制算术具有环绕功能所施加的自动模运算是为什么这样做有意义的另一个示例。

兼顾

要考虑的另一件事是,使用基于零的数组的第一个元素非常容易。(这不适用于foreach将数组作为一个整体对待的-style迭代和类似的语言构造。)许多程序员(包括我本人)对浪费的空间可能会感到有些尴尬,但是在大多数情况下,数量如此之小,以致于这些后顾之忧是没有根据的。另一方面,如果语言正在使用基于一个的索引,那么没有大量代码就无法模拟索引为零的元素。因此,鉴于在某些情况下,从零开始的索引比基于一的索引更好,所以在任何地方都选择零作为索引 与基于各处的基于位置的方法不同,它是一种更灵活的方法,并且比可配置的起始位置更加一致。


0

计算机系统同时使用自然数(从0开始计数)和整数(从1开始计数)。人们用整数对事物进行计数,这使它们对于编号列表很直观,许多编程语言都利用了这一优势:BASIC,COBOL,Fortran,Lua和Pascal都从1开始计数。这些语言的目标是数据处理,数值分析,和教学,其中简单,直观的列表是一个优势。

当您开始分析和处理数据结构时,整数会变得笨拙,而不仅仅是按顺序处理所有数据。当您需要在公式或算法中引用序列时,将它们从0进行编号更容易且更容易出错,就像数学家所做的那样:a 0,a 1n等,否则,您通常必须调整+1和–1来获取正确的数据,并且很容易出错,从而产生错误。因此,为计算机科学家设计的语言通常使用自然数:C,Java和Lisp都从0开始计数。

除编程语言外,许多计算机系统都从0开始编号,因为这是计算机科学家习惯的。同样,因为从1开始编号会导致许多隐患,所以我们中许多人在严格为非技术最终用户设计的界面元素之外避免使用它。


Java ...适用于计算机科学家。大声笑!
卡兹(Kaz)

0

简单的答案是第一个数字不是1,而是0。

说明:用于计算任何基数的多位数的公式为:

n = sum(i=0 to n, Di^i)

WHERE 
n = numeric result
i = index (starting with 0)
Di = is the digit at index i

让我们以十进制表示,这是我们最常用的十进制。

查看数字1234,我们可以将其写为:

4 x 10^0 = 4
3 x 10^1 = 30
2 x 10^2 = 200
1 x 10^3 = 1000

in other words, sum of digits raised to the power if their index.

因此,不仅仅是计算机,我们人类也从零开始计数。


0

数组索引是从基本存储位置到元素的存储位置的偏移量。则元素i为Base + i。第一个元素位于基本位置,因此它位于位置0(基本+ 0)。


0

除了计算效率外,还有另一个方面需要计数。有两种方法可以为序列中的每个元素赋予序号:

  1. 前面(整个)元素的数量(基数)
  2. 元素的位置(序号)

人们的年龄是基数:婴儿出生后的第一年为0岁,因为它已经存在了整整零年。

日期中的年份是序数:在第一年Anno Domini(AD)中,年份是1 AD。没有年,就像没有

编程语言(例如Matlab和Mathematica),其中元素的索引代表其在数组中的位置,从1开始,即第一个元素开始计数。在其他语言(例如所有基于C的语言)中,元素的索引是前面元素的数量,因此第一个元素是0。


当然,当指出基于零的索引更有效时,Matteo只是部分正确

element(n) = address + n * element_size

如果所有数组地址都已element_size减去一个,则基于1的索引可以同样有效。这可以在分配数组时完成,在这种情况下,速度一样快:

array_address = address - element_size
element(n) = array_address + n * element_size

-1

传统上,计算机计算从零开始的数值。例如,基于C的编程语言中的数组从索引零开始。

0…您搞砸了不同的概念:编程语言,计算机和计数。

  1. 使用2个状态(它们中的大多数示意性地做到这一点)意味着您可以选择2个数字将它们映射到(例如,参考)。“ 3”和“ 5”(或“ F”和“,”)可以,但是您会问为什么计算机从“ 3”(或“ F”)开始计数。自然选择显然是0和1。
  2. Pascal中的数组从1开始。该语言比底层C更抽象。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.