Counting naturally begins at zero
Here is the algorithm for counting apples in a basket:
count := 0 for each apple in basket count := count + 1
After the execution of the above, count
holds the number of apples. It may be zero, because baskets can be empty.
If you don't use your credit card for an entire month, do you get a bill of 1 dollar? Or 1 cent?
When you reset the trip meter on your car's odometer, does it go to 0001 or 0000?
Arrays can provide multiple views of the same data
Consider an array of 32 bit structures d
, which are each made of 16 bit words w
. Each word is made up of two 8 bit bytes b
. Under zero indexing, the overlay looks very convenient:
d: | 0 | 1 | w: | 0 | 1 | 2 | 3 | b: |0|1|2|3|4|5|6|7|
The 32 bit object d[1]
as at the word address w[2]
which is easily computed by multiplying the index by 2, which is the ratio of the sizes of the 32 and 16 bit object. Furthermore, in byte addressing, it is b[4]
.
This works because zero is zero, in every unit of measurement: byte, word, double word and so on.
Look at the above diagram: it looks much like a ruler, where unit conversions are intuitive.
With one based indexing, it breaks:
d: | 1 | 2 | w: | 1 | 2 | 3 | 4 | b: |1|2|3|4|5|6|7|8|
Now we cannot simply multiply the d
index by 2 to get the w
index, or by 4 to get the b
index. The conversion between units becomes clumsy. For instance to go from d[2]
to b[4]
, we have to calculate ((2 - 1) * 4) + 1 = 5
.
We have to subtract out that pesky 1 bias in the d
units, then do the scaling in the natural zero-based coordinate system, and then add back the pesky 1 in b
units. Note that it's not the same 1! We subtract one double word width, but then add in one byte width.
Converting between different views of the data becomes something like Celsius-Fahrenheit conversion.
Those who say that one-based arrays are easy to deal with at the implementation level, because there is just a simple subtraction of 1 are fooling themselves, and you. This is true only if we do not do any scaling calculations among different data types. Such calculations happen in any program that has a flexible view on data (e.g. a multi-dimensional array also accessed as a one-dimensional one) or that manipulates storage: for example, a memory allocator, file system, or video frame buffer library.
Minimizing Digits
In any base, if we want to use the fewest digits to implement a range of values which is a power of the base, we must start from zero. For instance, in base ten, three digits is enough to give us a thousand distinct values from 0 to 999. If we start from 1, we overflow by just one value, and we need four digits.
This is important in computers, because the number of digits in binary translates to hardware address lines. For instance a ROM chip with 256 words in it can be addressed from 0 to 255, which requires 8 bits: 00000000 to 11111111. If it is addressed from 1 to 256, then nine bits are needed. We have to wastefully add one more address trace to the circuit board or integrated circuit. So what would possibly happen in practice would be that 0 would just be called 1 at the software API level for accessing that chip. A request for word 1 would actually put 00000000 on the 8 bit address bus. Or else, a request for 1 would translate to address 00000001, as expected, but a request for 256 would map to the otherwise unused 8 bit address 00000000 rather than the 9 bit address 100000000. Both of these bag-biting kludges are really solutions in search of a problem, and are avoided entirely by consistently using 0 to 255 at the hardware, in the software and in all user interfaces and documentation.
One-based displacements are fundamentally stupid
Consider Western music theory for instance. We have diatonic scales with seven notes, but we call the space which they cover an octave! Inversion of intervals then follows the rule of nine: for instance the inversion of a third is a sixth (subtract three from nine). So three different numbers are at play for something so simple: seven (notes in a scale), eight (octave) and nine (subtract from to invert).
If seven notes made a septave or heptave, and intervals were zero based, then we would subtract from seven to invert. Everything based on seven.
Furthermore, intervals could be easily stacked. In the current system, if we leap by a fifth and then by a fourth again, and then by a third, we cannot just add these. The resulting interval is two less. It is not a twelvth, but actually a tenth! At each stage, we have to subtract a one. Going up by a fifth and then a fourth isn't a ninth, but only an octave.
In a sanely designed music system, we could just add intervals to determine the resulting leaps. A sequence of notes which begins and ends on the same note would then have a property similar to the voltage law around a circuit: all the intervals would add to zero.
Music theory and writing is badly outdated. Most of it has not changed since the days composing was done with quill pens by the light of a candle.
One-based systems confuse the same people who can't handle zero-based arrays
When the year 2000 rolled around, many people were confused why the new millennium hasn't begun. Those pointing out that it won't begin until 2001 were regarded as party poopers and dweebs. After all, you're in your 20's when you turn 20, right? Not when you turn 21. If you thought that the millennium started on January 1, 2000, then you have no right to complain about zero based arrays in any programming language. They work how exactly how you like. (But, yes, proponents of one-based displacements and arrays are dweebs and party-poopers. Centuries should start on the XX00 years, and millennia on X000 years.)
Calendars are dumb, but at least time of day is zero based
Each new minute on your watch starts with :00 seconds. Each new hour starts with 00:00 minutes and seconds. And, at least on a 24 hour clock, the day rolls around when midnight strikes and 11:59:59 increments to 00:00:00.
Thus if you want to calculate seconds from midnight for a time like 13:53:04, you just have to evaluate 13 * 3600 + 53 * 60 + 4
. No insipid 1
additions or subtractions.
Closing rant about MIDI
Okay, what is it with musicians, even supposedly technical ones?
MIDI! It uses zero-based numbering for programs and channels in the actual wire representation of messages, but gear displays it as 1 based! For instance programs 0 to 127 are called 1 to 128 on most gear, but some calls them 0 to 127 or even gives the user a choice.
Programs 71 through 80 are a considered a "bank" of ten. It says so right on my MIDI pedal, for example. The footswitches are labeled from 1 to 10 and if I'm in the seventh bank, they pick programs 71 through 80. However, some devices or computer software displays the 1-128 program numbers as 0 to 127, or even gives the user a choice! What is worse: one-based systems, or chaos created by using both one and zero based at the same time?
MIDI channel numbers are called 1 to 16, but are represented by 0 to 15 binary. As if out of spite for the one-based presentation, some gear uses a dispswitch for configuring a channel number and, often, thes switches just use the zero based binary code. So if you want channel 3, you must toggle it to 0010 (binary 2).