> Message: 6
> Date: Fri, 2 Jan 2004 10:49:52 -0600
> From: Terry Hancock <hancock(a)anansispaceworks.com>
> Subject: In defense of 0, was Re: [Edu-sig] None potato, one potato,
> two potato, more..
> To: edu-sig(a)python.org
> Message-ID: <m1AcSNH-007muwC(a)mail.augustmail.com>
> Content-Type: text/plain; charset="iso-8859-1"
>
> I have always had a tendency to think in "real number"
> terms when it comes to indexes. That may be an artifact
> of the fact that my experience with programming is largely
> with scientific and image-processing tasks, where the array
> (or "list" as Python calls it) is a *sampling* of a
> *continuum* instead of a collection of things.
>
> But whatever the reason, I personally find that Python's
> indexing is the MOST intuitive of all schemes I've yet seen,
> particularly as regards "slices" and ranges.
>
> If you think of an array as being depicted like a
> numberline, with the spaces between the numbers as the
> "boxes" into which data values are put, then the notation
> makes immediate sense:
>
> * Underline what you want.
> * The endpoints of the underline are the python slice
> values.
>
> So if you want the first element only, you want [0:1],
> if you want the next 4 you want [1:5]. Also, the size of
> the array is (intuitively! everybody believes this until
> they are taught otherwise) the subtraction of the two
> quoted indices -- len(a[1:5]) = 5-1 = 4. I.e. it works
> just like a real-number range, not like integers. Also,
> [0:0] means the empty list, as it seems like it should.
>
> Now, of course, I *know* the importance of actual
> integer math, and I can't quite forget about it because
> of this -- but it does mean that I don't have to think
> about it every single time I use an index in Python.
>
> Generally, I just have to think about on the few occasions
> when these kind of details are actually important.
>
> By contrast, I had endless headaches with both FORTRAN (1
> to N) and C (1 to N-1) indexing schemes, especially with
> regard to image and spectrum processing routines. Ironic
> that these are the preferred choices for scientific
> programming. Python's scheme is brilliant, because I
> almost never have to use i+1 or i-1 notations. The number
> of classic "off by one" errors that I make today is vastly
> lower than it used to be. I used to spend hours tracking
> things like that down.
>
> The other thing that helps so much is Python's negative
> index slicing -- where negative indexes are determined
> from the end of the array. That's a terrific help, since it
> avoids all the tedious nonsense of finding out the length
> of the array and figuring out offsets from it directly.
> It's much easier to just write [-4:] and know you're
> getting the last four elements. Once again, this saves
> me from "a[len(a)-1]" and similar obfuscation.
I've always told students that the advantages of 0-based indexing are:
- it's slightly simpler to implement when you are using the C model of
memory (i.e. array locations are offsets from a base address)
- when you are using modular arithmetic to calculate index values,
like (i % num_rows), then it is often convenient to have the array start
at 0 because the % function naturally returns a 0
- when you want to calculate the length of the slice lst[a:b] (where a
and b are non-negative), its simply b - a
- 0-based indexing makes the most sense if you think of the index
values as distance measures from the start of the array, just like a
ruler (as Kirby mentioned). With 0-based indices, programmers must come
to grips with ugly statements like "lst[0] is the first element of lst".
- 1-based indexing makes more sense if you think of the index value as
ordinals, i.e. if you want to count the elements of the array. This is
traditional in CS, e.g. see Knuth's The Art of Computer Programming.
Exercise 19 of section 2.2.2 asks readers to convert some of the 1-based
indexing to 0-based indexing.
Toby
--
Dr. Toby Donaldson
Assistant Professor
School of Interactive Arts and Technology
Simon Fraser University