bwD*_*aco 55 computer-architecture computer-science
计算机传统上从零开始计算数值。例如,基于 C 的编程语言中的数组从索引零开始。
这有什么历史原因,从零开始计数比从一开始有什么实际优势?
注意:这个问题要求得到解释清楚的技术答案,而不仅仅是意见,并且旨在涵盖一般的计算机,而不仅仅是编程。这个问题扩展了程序员的问题“为什么结构/数组从零开始?” .
Mat*_*teo 89
从 0 开始计数数组简化了每个元素的内存地址的计算。
如果数组存储在内存中的给定位置(称为地址),则每个元素的位置可以计算为
element(n) = address + n * size_of_the_element
Run Code Online (Sandbox Code Playgroud)
如果您首先考虑第一个元素,则计算变为
element(n) = address + (n-1) * size_of_the_element
Run Code Online (Sandbox Code Playgroud)
没有太大的不同,但它为每次访问增加了不必要的减法。
编辑
使用数组索引作为偏移量不是必需的,而是一种习惯。第一个元素的偏移量可以被系统隐藏并在分配和引用元素时考虑在内。
Dijkstra发表了一篇论文“为什么编号应该从零开始”(pdf),他解释了为什么从 0 开始是更好的选择。从零开始可以更好地表示范围。
Dou*_*gvj 38
虽然以下原则适用于十进制以及任何其他基数,但从计算机中使用的表示数字的固定数字二进制系统很容易自然地理解计算机中从 0 开始计数。如果您有 8 位,则可以表示 256 种可能的 1 和 0 组合。您可以使用这些 8 位来表示数字 1-256,但这会忽略在数学中作为数字本身很有用的 0,因此它们用于表示数字 0-255。
这已经开创了从 0(二进制表示中全为 0)到 255(8 位数字中全为 1)的自然顺序的先例。考虑到表示数字的系统,从 0 开始是有意义的,因为 0 是系统中的“第一个”数字,因此 1 是“第二个”数字,依此类推。
在计算机中从 0 开始如此方便的另一个原因是偏移的概念。偏移量是一个数字,表示与内存或硬盘或任何其他“可寻址”介质中某个位置的距离。在计算机中,几乎所有数据都是线性存储的,这意味着数据有一个顺序,第一个字节,第二个字节等。通过偏移量来表示数据“区域”的位置很方便。数据块中的第一个字节是什么?它位于偏移量“0”处,这意味着它位于数据块中第一个字节之后的 0 个字节处。虽然可以用“1”指定第一个字节,但由于以下几个原因,这会导致数据表示变得复杂:
Яро*_*лин 27
从未想过像我这样的扶手椅哲学家的机会会出现在超级用户身上。这里有一个根本性的误解,因为非哲学家往往会跳过细微的细节。简而言之: 计算机不从零开始计数,但头寸的面额从零开始。
计算机和人类(任何)计数技术之间的这种感知不一致并不令人困惑。让我们分解这个问题。
为什么计算机从零开始计数?
计算机从零开始计算值。例如,C 中的数组。
零实际上表示某物的空白或比例的中间点。计算任何东西都不切实际,因为根据零的定义这是不可能的。
与标度的中点相同,零可用于表示集合的最边缘(绝对开始)。这个问题毫无意义,因为它在“计数值”和“从零开始计数”之间是不一致的。
所以是的,计算机确实从零开始计数,但它们从一开始计数。这两个词具有不同的含义。
名词
动词(与宾语连用)
(dictionary.com)
Dougvj 充分描述了实际原因,我没有什么要补充的。如果我们能有一位 CS 教授(从 60 年代开始)来提供历史记录就好了……
Nev*_*DNZ 13
我认为“ Edsger W. Dijkstra教授” - Burroughs研究员在 1982 年 8 月 11 日的一封信中已经涵盖了这一点:cf EWD831
标题:为什么编号应该从零开始。“有没有理由更喜欢一种公约?是的,有……”
另请注意,Dijkstra直到 1968 年才加入ALGOL 68设计团队。Algol68 允许数组为 0、1 或程序员认为适合算法的任何数字。cf(“Algol 68 的制作”讲述了“你能定义三角形阵列吗?”有人(Tony Hoare?)打断道。“不仅是三角形,甚至是椭圆形”Aad 回答说,并展示了如何定义。')
具体来说,在 Algol68 中,当数组(& 矩阵)被切片时,它们会得到一个索引 @1,因此对 [1:...] 数组有偏见。但是“第一个”下界可以通过指定“@0”移动到“第0个”位置开始,例如向量x[4:99@2],矩阵y[4:99@1,4:99 @0]。类似地,在do ~ od循环中有一个默认/偏差为from 1 (除非明确说明“ from 0”),对于整数情况i in ~,~,~ esac和 $c(~,~,~ )$选择子句。
Dijkstra 对 1968 年 3 月的报告草案 ( MR93 )的评论和他的坚持似乎引发了一场可以说是 usenet 前的火焰战争:“有些作品虽然不合语法但很可爱,还有其他一些非常符合语法的作品,但恶心。这是我无法向肤浅的人解释的事情。” EWD230
Algol 68 最终报告 (FR) 于1968 年 12 月 20 日发表,当时在慕尼黑会议上遭到了反对,然后被工作组通过。随后,该报告经教科文组织IFIP大会批准出版。
1968 年 12 月 23 日(?)左右,Dijkstra、Duncan、Garwick、Hoare、Randell、Seegmuller、Turski、Woodger 和 Garwick 签署了AB31.1.1.1“少数派报告”,第 7 页(1970 年出版)。
Ran*_*832 10
其他人提出的距离类比非常实用:
“你家离最近的加油站有多远?”
“一英里。”
“你住在加油站?”
“不,如果我住在加油站,那就是 0 英里”
“你为什么从零而不是从一开始数?”
另一个很好的例子是生日——我们不会说某人出生那天是一岁,我们说是一年后。
我们说闰年或美国总统选举是每四年一次,即使您从一年开始:2000 年、2001 年、2002 年、2003 年、2004 年是五年。(顺便说一句,罗马人确实搞砸了一段时间,并且闰年靠得太近了)
我的观点是,我们在现实世界中一直从零开始“计数”——“[数组开始] 之后有多少个位置是您想要的元素”恰好是您要回答的问题,从零开始计数在许多计算机程序中。你不会说第一个元素是开始后的一个位置,对吗?这是开始。
正如其他人所说的,计算机不是从零开始计数的。
有些语言从 0 开始索引。从 0 开始索引有两个主要优点:
它以自然的方式转换为汇编,因为它可以解释为从指针到第一个位置的偏移量。
当你想要底片时,你不会感到奇怪。1BC 和 1AD 之间有多少年?没有任何。因为尽管 BC 实际上是负日期,但没有零年。如果有 0AD,这里就不会有任何问题。你在科学中到处看到同样的问题,人们天真地将集合中的第一个元素定义为 +1。