跳转到内容

从零开始的编号

维基百科,自由的百科全书

从0开始编号索引开头为0是一种编号方式,其指一个序列的初始元素的索引被分配为0,即序列的编号从0开始,而非从1开始。在从零开始的编号方式下,序列中初始的元素有时会被称为第零元素(一般称为第一元素)。

某些情况下,不属于该序列但可以放置在其之前的物件被称为“第零元素”。使用零作为序数并未被广泛接受,因为在缺乏上下文时,序列的所有后续元素会出现混淆。

尽管数学领域的编程语言通常从1开始编号,但从0开始编号的序列在数学符号中仍然是相当常见的,特别是在组合数学中。计算机科学中,一些现代编程语言(例如C语言)的阵列索引通常从0开始,与通常使用“第一”开始索引不同,编程人员可能会用“第零”开始。在数学中对于出现在“第一个”之前的元素,其序数形式有明确的定义时,使用从零开始的编号不会造成混淆;例如函数的第零阶导数是进行零次微分获得的,亦即函数本身。对应于不属于该序列,但以这种命名法命名在其前面的元素,或不妥当:所谓“第零阶”的导数实际并非导数。然而,正如一阶导数在二阶导数之前,因此第零阶导数(或原始函数本身)也在一阶导数之前。

编程

起源

计算机编程中列举数据从零开始编号,主要起因于提供的机器指令,根据条件判断,程式要能在指令序列之间“跳转”,这是实作分支结构的关键。可用条件以判断暂存器内容的“零”和“负”为主。最常用于实作迭代的指令譬如“递减,如果到零就跳转”。也就是说,任何可列举的数据结构都在迭代中循环处理,而是否为零的条件判断,用于控制这些循环的执行(不为零就一直在循环中)。高阶编程语言的循环结构(如do-while,repeat-until,for-step-to...)是基于这些根本的机器指令。

BCPL编程语言(C编程语言的前身)的创建者,马丁·理察德(Martin Richards)设计了阵列从0开始的索引方式,作为存取阵列开头内容的自然位置,因为表示位址的指针p值,用于存取记忆体中的p+0位址;系统分析师Mike Hoye询问Richards选用该惯例的原因。BCPL最初是用IBM 7094机器编译的;它在编译时会优化这些阵列索引提供的指针反参考运算(indirection)。

在1982年艾兹赫尔·戴克斯特拉(Edsger Wybe Dijkstra)写了个相关的说明《为什么编号应该从零开始》,将阵列索引的上下界以不等式连接,来分析各种设计方案,列举出严格和标准不等式的四种可能组合,展示了他的确信,从零开始编号的阵列不会造成索引范围重叠,是最好的表示方法,从零开始暗示与实数同样的开,半开和闭区间。偏好这惯例的细节以空序列说明,它可以用更自然的(a≤i<a?)不等式来表示,相较于用闭合“区间”的(a≤i≤(a-1)?)不等式。而且以自然的半开“区间”不等式来看,子序列的长度等于上界减去下界(a≤i<b给出(b-a)的i可能值,其中的a,b,i都是自然数)。

编程语言用法

这种设计方案嵌入在许多具影响力的编程语言中,包括C,Java和Lisp。在这三种语言中,序列类型(C阵列,Java阵列和串列,Lisp串列和向量)以数字零为下标开始索引。特别是在C语言中,阵列与指针运算紧密相关,这使得一个更简单的实现:下标的参考是从阵列起始位置的偏移,因此第一个元素的偏移量就是零。

几乎所有计算机结构,都借由位址和偏移量来表示直接引用内存,因此C语法的设计细节使编译更容易,但代价是一些人工成本。这样的情况下,使用“第零”作为序数并不是严明正确的,而是计算机业界的普遍惯例。其他编程语言如Fortran或COBOL,则有从一开始的阵列索引下标,因为它们意味着高阶编程语言,因此它们必须与通常的序数相对应。一些最近的编程语言如Lua,由于同样原因采用了相同的约定。

零是最低位的无符号整数值,是编程和硬件设计中最基本的类型之一。因此在计算机科学,零经常被当作许多种类的数值递归的基本情况。计算机科学中的证明和其他类型的数学推理通常从零这一数开始。由于这些原因,在计算机科学中,从零而非从一开始计数的方式并不少见,时有用例。

黑客和计算机科学家经常喜欢将出版品的第一章,如果其内容特重于介绍的概念,则称为“第0章”。其中一个经典的例子是在K&R的第一版。近年来在许多纯数学家中也出现这种特征,许多构造被定义为从0开始编号。

如果用阵列表示循环,则模除(modulo)函式即可便利地获得索引,而这会导致结果为零。

数值属性

使用从零开始的编号范围表示为半开区间,不同于闭合区间。在算法中经常发生的“空”范围,很难以闭合区间[1,0]来表达。由于这个属性,从零开始的索引潜在地减少了差一和栅栏错误。但另一方面,预先扣除掉重复的计数,使得从(包含)的表达较不直觉。有些作者更偏好从开始的索引,因为它直接对应了该项目在其它段落中的索引。

零索引惯例的另一个特性是在现代计算机中实作的模运算。通常,模函数将任何模映射到中的一个数字,其中。因此在算法(例如计算杂凑表索引)中的许多公式,当序列从零开始索引时,使用模运算可优雅地以代码表示。如上文所提及位址/偏移量的底层逻辑,指针操作也能以零索引更优雅地表示。

为了说明,假设是阵列中第一个元素的内存地址,是需求元素的索引。要求所需元素的位址,如果从开始计算索引号,则通过以下表式计算:

,其中是每个元素的大小。若从0开始计数,则表达式变为:

,这个简单的算式可在执行时期更有效率地计算。

然而注意,从1开始索引阵列的语法也能从简采用约定:每个“阵列位址”以

来表示;

也就是说,不采用阵列中第一个元素的位址,这种语法使用某个“虚拟”元素的位址,紧接在实际的第一个元素之前。从1开始索引的表式如下:

因此零索引的执行期效率来自以0暂代第一元素的实际位址,不使用阵列之前的“虚拟”元素位址,此设计策略的优势。可是,直接位于阵列之前的“虚拟”元素位址,或许是与阵列无关的其他项目,能有作用的位址。这种情况可能导致术语上的混乱。

在零索引方案中第1个元素是“下标零”;同理第12个元素是“下标11”。所以从序数到物件数量的转换浮现;n个元素的最高索引会是n−1并且被称为第n元素(表示数量为n,上界索引与计数差一)。反之第一个元素就被称为第零物件(直接以序号指称),以避免混淆。

科学

在数学中,许多数字序列或多项式是以非负整数来索引,例如伯努利数贝尔数

热力学第零定律是在第一和第二定律之后才提出的,但因为比其它定律更为基本,所以称为热力学第零定律。

在生物或医学实验开始前的初始测量,被称为此实验的第0天。

第零个病患(或指标病例)是流行病学调查群体样本中的初始病患。

参见