昨天看到一个有意思的问题,为什么在我们遇到的大多数编程语言里面,数组的下标基本都是从0开始? 这是一个简单的问题,很少人会有人去思考为什么,但这里面其实是有一定的数学逻辑在里面。像目前主流的编程语言C/C++,Java,JavaScript的数组下标都是以0开始,最后一个位置的index=数组的长度-1,当然也有少数的编程语言如Fortran,声明一个a(10)默认就是从1开始的,当然你可以指定从0开始,需要换种方式声明a(0:9)。 那么为什么应该从0开始而不是1呢,这在计算机科学里面是一个有趣的概念。首先,它与语言的设计有很强的关联,比如在C语言里面,数组的名称本质上是一个指针,它代表了内存里面存储这块连续区域的开始地址,array[n]代表的是 n-elements 距离开始位置的距离,这本质上是通过offset也就是偏移量实现的。所以数组里面的第一个元素是用0表示的,这么说大家可能还是迷惑,说的再直白点,比如在Java里面的一个int数组,因为int是32位,在数组里面的第一个元素可以理解成是[0,32)这段区间内的值,因为起始位置是0,所以简单记为0即可,因为数组的类型长度都是固定的,比如int是32位,long是64位,所以通过起始位置+类型的长度就可以推算得到任何一个index的值,比如3下标的数据,可以通过[332,332+32)得到值,不难发现数组的下标起到了很大的简化作用。由于C语言出现的比较早,且非常经典,后来的语言都借鉴或者保持了这种特色。 当然,上面是纯粹从编程语言层面讨论的,其实在数学领域,也有比较形象的解释,假设我现在有一个连续的自然数序列,1,2,3...一直到10,现在如果想要表示这段数组,通常有四种表示形式: a. 0<i<11 b. 1<=i<11 c. 0<i<=10 d. 1<=i<=10 正确的标记方法,在自然数的范围内应该包含下面的两种情形: (1)子序列可以包含最小的自然数0 (2)子序列可以是空的 下面我们来看下,上面的四种方法应该使用哪种比较适合。首先,对于要求1可以包含最小的自然0,我们会发现a和c的标记法是没法表示0的,除非写成-1 for(i=0;i<N;i++){ sum+= a[i]; } 至此你应该了解为什么数组的下标要从0开始了,我们写过很多遍的for循环语句,虽然简单,但本质上却蕴含了一种朴素的数学之美,世界之奇,莫过如此。 |
|