
Why numbering should start at zero (1982) - pcr910303
https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html
======
Animats
Depends on whether you're measuring or counting.

The article mentions Mesa's interval syntax, which gave programmers all the
possible options:

[1..100] (0 .. 101) [1 .. 101) [1 .. 101)

were all the same interval, 1 to 100 inclusive. Bad idea. Great way to get
off-by-one errors.

Another bad idea from that era - Wirth's insistence that you shouldn't be
allowed compile-time arithmetic in Pascal. Like.

    
    
        const
            tabsize = 100;
    
        var 
            tab: array [0..tabsize-1] of integer; { NOT ALLOWED }
    

No, you had to have a separate named constant for "tabsize-1", and it couldn't
be initialized as "tabsize-1", either.

~~~
Someone
_”Bad idea. Great way to get off-by-one errors.”_

I would think that depends on whether that gets taught at schools early in
life.

Intervals that are closed at the low and open at the high end also are
convenient when using zero-based indexing (you want an easy way to express
0,1,2,…,n-1, and if you’re used to the notation [0,n) is nicer than [0,n-1])

I would think overloading the meaning of the various parentheses makes parsing
and generating clear error messages harder, though (but not as hard as when
one would follow ISO 31-11 and allow such things a _]3,7]_ for an half-open
interval excluding 3, but including 7)

I think the desire to not overload parentheses with yet another meaning is why
‘Modern’ languages tend to use an infix operator for ranges, e.g. ‘1 to 5’ or
‘1...5’, with Swift having the half-open variant ‘1..<5’ (IMO ugly, but clear,
so I guess one would get used to it).

~~~
WalterBright
> 'Modern' languages

After having many fencepost errors, I finally came to the conclusion that all
my code shall henceforth be zero-based. I'm much happier not having those
errors anymore. I.e.:

    
    
       for (i = 1; i <= N; ++i)
    

The <= is always a huge red flag for me, and I rewrite it as:

    
    
        for (i = 0; i < N; ++i)
    

and add a `1` in the body if I must.

~~~
chopin
Any specific reason to use _++i_ over _i++_? I always use the latter but only
out of habit. I've rarely seen code with the former (your idiom).

~~~
WalterBright
It's just better form. Also, if `i` is a struct with an overloaded postinc
operator, it can be more expensive.

~~~
chopin
Yeah, but why is it better form (I am coming from Java where it shouldn't make
any difference)?

~~~
WalterBright
It's better form to not ask for a characteristic that you don't need.

For example:

1\. increment x

2\. take the value of x, then increment x

(1) is better form if you don't need the value of x.

~~~
chopin
I just checked in Java, it is:

1\. increment x, then take the value of x

2\. take the value of x, then increment x

Both are expressions in Java returning a value. My C is very rusty but I
remember it being the same in C.

------
raymondh
Python follows convention the first convention, just as Dijkstra recommends.
Mostly this worked-out well except for the case of descending sequences.

With half-open intervals, that case proved to be cryptic and error-prone, so
we added reversed() to flip the direction of iteration. That allowed people to
easily bridge from the comfortable and common case of looping forwards.
Instead of range(n-1, -1, -1) we can write reversed(range(n)).

~~~
mikepurvis
I was intrigued to see how this worked out in practice for Python 3, where
range returns an iterator rather than a list— like, would reversing the
iteration require allocating the whole list in memory?

    
    
        $ python3 -c 'print(reversed(range(10)))'
        <range_iterator object at 0x7fdb53ae96f0>
    

It turns out that reversed() only works on objects that expose the __len__ and
__getitem__ methods:

[https://www.python.org/dev/peps/pep-0322/](https://www.python.org/dev/peps/pep-0322/)

If you try to use reversed() with your own generator it will fail with
"TypeError: argument to reversed() must be a sequence", until you wrap the
generator invocation in an explicit list().

Very nice.

~~~
kragen
Alternatively the object can expose a __reversed__ method, which is why
reversed(range(10)) is a "range_iterator object" rather than a "reversed
object".

------
protonfish
The first time I read this, I was ready to be convinced and left disappointed.
His entire argument is based on avoiding "the pernicious three dots."

What's so pernicious about them? They are short, clear, unambiguous, easy to
type. Why don't we just get our computer languages to understand what "2, 3,
..., 12" means? Is there any other argument to start counting at 0 other than
not defining a range using the three dots? If not, maybe starting at 1 (like
everyone does outside of computing) is the better option.

~~~
crooked-v
> Why don't we just get our computer languages to understand what "2, 3, ...,
> 12" means?

Some languages already do: for example, in Ruby you can use (-5..-1) to get
[-5, -4, -3, -2, -1]. It's lazy evaluation, so you can even do stuff like:

    
    
        Infinity = 1.0/0.0
        (1..Infinity).step(2).take(5) #=> [0, 2, 4, 6, 8]

~~~
mark-r
I remember seeing a rather convincing argument that 1.0/0.0 should not be
infinity, but zero.

~~~
QuinnWilton
This is how Pony handles division. There's a good summary of possible
motivations here: [https://www.hillelwayne.com/post/divide-by-
zero/](https://www.hillelwayne.com/post/divide-by-zero/)

~~~
QuinnWilton
I pasted the wrong link above, but my mobile app isn't letting me edit it.
This is the link that describes their reasoning:
[https://tutorial.ponylang.io/gotchas/divide-by-
zero.html](https://tutorial.ponylang.io/gotchas/divide-by-zero.html)

------
0-_-0
Lots of people have a strong opinion on this: Ones that say that 0-based
indexing is the only logical way of things, and ones that don't see what the
fuss is about and prefer 1 because that's how we count objects. I suspect the
people in the first category did some low level programming that needed to do
arithmetic on indices. For example, let's say you want to take a string "abc"
and repeat it until the length is 10, getting "abcabcabca". Assuming some
Python-like language you would start with:

    
    
        a = "abc"
        b = [" "]*10
    

With 0-based indexing you would do:

    
    
        for i in range(0,10):
          b[i]=a[i%3]
    

In a 1-based language that becomes:

    
    
        for i in range(1,11):
            b[i]=a[(i-1)%3+1]
    

So you need to shift the index twice. This is because modulo arithmetic needs
0 to form a ring. As a result, in situations where the difference between 0
and 1 based indexing makes a difference it's ususally 0-based indexing that
leads to simpler code.

~~~
kragen
Dijkstra makes, I think, a stronger argument, particularly given that in
languages like C, (-2) % 3 == -2 rather than 1 as it should.

~~~
wnoise
This used to be unspecified behavior. C99 then codified this wrong behavior.

Assume positive b for a moment. We want a * (a/b) + (a%b) = a. If a%b is to
always be within [0..b), then a/b has to round toward -infinity. C99 instead
chose round towards 0.

~~~
derriz
Don't you mean we want "(a/b) + (a%b) = a"?

~~~
a1369209993
> We want a * (a/b) + (a%b) = a.

> Don't you mean we want "(a/b) + (a%b) = a"?

No, they mean " _b_ * (a/b) + (a%b) = a". (Also I'm not convinced that's
actually useful, but that's a different discussion.)

~~~
derriz
Ha - you’re correct of course. I saw the a^2 term and thought that can’t be
right. Note to self - before attempting to correct others, check the
“correction”.

------
eigenspace
Very subjective and context specific argument.

Some things are more naturally numbered from 1, others from zero. Fence posts
versus fence spans.

Pointer arithmetic is a great example of a situation well adapted to 0 based
numbering, and was quite relevant to many programmers when this was written.
However, far fewer programmers nowadays interact with raw pointers directly.

Personally, I run into more cases where I’d rather have 1 based numbering than
zero, but your mileage may vary. It’s valuable to have a language which can
support both.

~~~
asveikau
> However, far fewer programmers nowadays interact with raw pointers directly.

It doesn't have to be literally a memory pointer to run into the same
phenomenon. For example, offsets into a file. I can think of an example when I
was doing work on a file format, and 0 based indexing certainly helped
simplify some logic.

~~~
eigenspace
Correct, I was merely pointing out that the main motivator of Dijkstra’s
argument is not nearly as relevant as it was when this was written.

I have no idea what indexing style is more appropriate to the hypothetical
‘average’ programmer, but I find myself preferring mostly 1 to N the most,
followed next by -N to N and finally 0 to N.

As I said originally, your mileage may vary, but I think it’s important that
we use languages where many different indexing styles can be supported
ergonomically, and in a way that avoids silly errors due to using the wrong
index style.

Type systems and generic functions help a lot with this. I think of it a lot
like say, signed versus unsigned integers. Multiple useful ways of looking at
the same bitwise data. Type systems generally save us from nasty errors with
the various types of integers. They can do it with arrays too.

~~~
daveFNbuck
Do you have any examples where 1 to N is a more convenient numbering?

~~~
eigenspace
What are the second to fifth elements of the array A?

    
    
        A[2:5]
    

I find that much much more convenient and user friendly than the alternative.

------
tabtab
In the business domain one is often counting and tracking explicit things:
widgets, contracts, customers, complaints, pizzas, etc. When counting, you
almost always start with 1. "1" fits the domain more naturally, and if you
deviate, you'll likely spend code converting between the end-user's view and
the code's view. The translation layer creates risk of errors and more code.
Maybe weather forecasting or space probe orbit calculation is different, but 1
better fits biz. Dijkstra was not (primarily) a business domain coder.
(Smarter languages, like Pascal, allow you to define the range, although I'm
not sure if it has dynamic upper ranges.)

~~~
tomjakubowski
I think you'd still start counting those things from 0, because it's a
convenient and natural way to express that you don't have complaints, widgets
or pizzas.

Or, I suppose, you could start counting at 1, but use an optional type and use
None for that case. But that makes doing arithmetic on those numbers ("widgets
per pizza") harder than if you'd just used 0 to begin with.

~~~
tabtab
I think you are mixing up indexing and default value setting. They are roughly
related, but only roughly.

~~~
marcosdumay
Hum, no. He is using a generalized version of counting that works for 0 items
too.

A computer should start counting from 0, there's no reason to special case the
empty set.

~~~
mjevans
Humans should too for the same reason.

Lets consider a measuring tool for fluids which is based on volume. What is a
useful range for the index on the side that measures the currently non-air
capacity?

Many such devices, E.G. a measuring cup I've got at home in the kitchen, use a
series of tick marks within a bounded scale of accuracy range ] with marks on
both the top (of course) and also the bottom (it looks nice).

While 0 isn't expressly labeled on many scales, it is part of the inclusive
range by implicit nature. Thus as you point out the case of 0 units, and
'empty set' are one and the same in this real world example.

~~~
chupasaurus
You forgot to explicitly mention that bottom mark on your measurement cup is
indeed 0, and without it you could measure "at least this volume of fluid".

~~~
tabtab
That doesn't change anything that I see. Indexes and counters are usually not
used for "continuous" metrics such as liquid quantities. And again, the biz
domain typically does not count fractional quantities, at least not in an
indexed way.

It's not a _practical_ problem for most coding. If you disagree, can you
demonstrate a problem caused by indexing arrays starting at one in a _typical_
code situation/scenario?

------
gjm11
The syntax I always want but no language I know of supports:

    
    
        for 1 <= i <= 10:
            do stuff
    
        for 0 <= i < 10:
            do stuff
    
        for 1 <= i < j <= 10:
            do stuff
    

(In the last case, the exact order in which the 45 iterations happen should
maybe be left unspecified; at any rate, it would be bad style to depend on
it.)

Downward iteration:

    
    
        for 10 >= i >= 1:
            do stuff
    

Obviously this doesn't cover every case of "arithmetic for loop" that would be
useful: sometimes you want a stepsize that's neither 0 nor 1. I'd be quite
happy with a language in which I had to do that using a more general iterate-
over-an-arbitrary-sequence construction; I'm tempted by options like

    
    
        for 100 <= i <= 1000 where i%3==1:
            do stuff
    

but it's probably too clever by half; either you only support the simple
"specify the value of the variable mod something that doesn't change while
iterating" case, in which case users will complain that some obvious
generalizations fail to work, or you support arbitrary predicates, in which
case you have to choose between making the "easy" cases efficient and the
"hard" cases not (in which case users will be confused when what seem like
small changes have drastic effects on the runtime of their code) and making
all of them inefficient (in which case users will be confused by how slowly
their code runs in some cases).

~~~
arh68
You may enjoy Common LISP's looping: it's a whole minilanguage where you can
say stuff like

    
    
        (loop for i from  1 upto   10 ..)
        (loop for i from  1 below  11 ..)
        (loop for i from 10 downto  1 ..)
        (loop for i from 10 above   0 ..)
        (loop for i from 3.5 to 7.5 by 0.25 ..)
    

It does much more than that, I should mention; it's a whole mini-language/DSL
(like format).

~~~
gjm11
Not only _may_ but _do_ ; I like Common Lisp a lot, and while some people
complain that LOOP isn't lispy enough I personally do like it.

But it doesn't have the elegance of just specifying the inequalities you want
your loop variables to satisfy :-).

------
paulmd
"Should array indices start at 0 or 1? My compromise of 0.5 was rejected
without, I thought, proper consideration."

\-- Stan Kelly-Bootle

~~~
travisjungroth
I made a Python library that implemented this and gave a talk about it at
PyCon:
[https://www.youtube.com/watch?v=yC9m2GInXqU&feature=youtu.be...](https://www.youtube.com/watch?v=yC9m2GInXqU&feature=youtu.be&t=330/)

~~~
andai
Gave me a good laugh, thanks for this :)

[https://github.com/travisjungroth/Compromise](https://github.com/travisjungroth/Compromise)

------
tenebrisalietum
On the assembly language level, you have compare instructions. These subtract,
and throw away the result, but leave the flags.

Many CPUs have a flag that is automatically raised if a value is 0.

This means you don't have to execute a compare instruction to test if a value
is 0, because the "Zero" flag will be set as soon as the 0 value is loaded.

That means you can load a value, and directly go to a BEQ (which is really
shorthand for "if zero flag = 0") and save a few cycles by avoiding the CMP
instruction.

So this is why numbering starts at zero. Testing if your list is empty, which
is probably a common thing if you loop through each element, is slightly
quicker.

~~~
kragen
A disappointingly large number of comments on this article are by people who
inexplicably offer weaker arguments than Dijkstra's.

------
snicker7
In scientific-oriented languages (R, MatLab, Julia, Fortran, &tc.), array
indicies tend to start at 1. I think it is a culture thing. Software engineers
prefer 0. Scientists prefer 1.

~~~
metalliqaz
The scientists can do what they want until they start using computers, then
they should listen to the software engineers.

~~~
Certhas
This is silly. Different domains have different needs. If you think of arrays
as pointer + offset calculation, and your only for loop has an explicit index
increment in it, then starting at 0 is natural. If you are a systems
programmer then a language targeting you should accommodate that.

If you are anyone who doesn't want to care (too much) about how things are
implemented, then it's a lot less error prone to mark the 1st element of an
array a[1]. Having taught and written fairly complex scientific code in both 0
and 1 indexed languages, there really is no good reason to do anything else.

    
    
        for a in array[3:6]
    

Should iterate over the third to sixth element of the array.

~~~
metalliqaz
I dunno man, it's Dijkstra's essay. He has a pretty good reputation.

------
linuxlizard
I'd like to have a keyboard with a 0 (zero) to the left of the 1 (one) digit.

~~~
mjevans
Learn to enter numbers with the 'ten key' 'num pad' on the right... or
possibly buy a full-sized keyboard.

------
dang
Discussed in 2018:
[https://news.ycombinator.com/item?id=17765034](https://news.ycombinator.com/item?id=17765034)

2016:
[https://news.ycombinator.com/item?id=13186225](https://news.ycombinator.com/item?id=13186225)

2015:
[https://news.ycombinator.com/item?id=9761355](https://news.ycombinator.com/item?id=9761355)

2009:
[https://news.ycombinator.com/item?id=777580](https://news.ycombinator.com/item?id=777580)

------
magicalhippo
I'm usually a start-at-zero guy, except if I'm implementing matrix routines...
going from the 1-based indexing from the math theorems to 0-based code is so
tedious in order to ensure the translation is correct.

------
HorizonXP
I totally agree with this. However, I'm trying to teach my 1 year old how to
count. He's got 1, and 2 down, and we're working on 3 (He can say the numbers
1 to 10, I'm talking more about the concept of numbers). I would love to get
him to understand 0 too, but I'm not sure how.

~~~
kazinator
> _He 's got 1, and 2 down, [...] He can say the numbers 1 to 10_

That's extremely amazing for a kid that is exactly one years old, rather than,
say, 1.x years old for high values of x.

~~~
travisjungroth
Seems like a very technical way to say “almost 2”.

~~~
pgcj_poster
Consider P₁ ∈ H and P₂ ∈ G where H is the set of HN posters, and G is the set
of persons in the general population. Let p(P U) be the probability that a
person, P, will produce an utterance, U, using mathematical terms and/or
notation. Let q(U) be the probability that U will be better understood in
mathematical terms than in plain language.

For any U, p(P₂ U) ≤ q(U) < p(P₁ U)

------
psychometry
There's not much reason in a high-level language to start at 0. Humans reason
about iteration in terms of the natural numbers.

~~~
wnoise
That doesn't help: mathematicians have two definitions for "the natural
numbers", one starting at zero, and one at one.

~~~
goatlover
The languages designed for scientific computing, which make heavy use of math
libraries, start at 1.

------
codeulike
Great to see this at position 1 on Hacker News

~~~
DonHopkins
It deserves to be at position 0.

~~~
goatlover
Position 0 doesn't exist.

~~~
DonHopkins
No, you just need to subscribe to HN Gold to see it.

------
oarabbus_
The worst is google sheets API, which uses Javascript-based 0-indexing for
some functions, but Excel-based 1-indexing for other functions. Nightmare!

~~~
mjevans
It's trying to replace/inter-operate with Excel, so it has to maintain
backwards compatibility; bug for bug, including design bugs.

I couldn't tell you offhand if the logic you speak of is distinct to Sheets or
if it's Sheets maintaining the same interfaces other spreadsheet software
defined for those macro names long ago.

------
javajosh
Counting a physical process, so you have to allocate space. 0 is that
allocation, and as you move along the number line, you update that space
(using "add 1"). Note that you only update the space at discrete intervals,
which has surprisingly deep implications.

Having a kid I've been thinking a lot about counting, and what it really is.
It seems totally wrapped up in repetition, and so I'm wondering if teaching
counting as a function of, say, circular motion doesn't give a better
intuition than the usual "count this clump of things" approach. (Counting
clumps requires the person to simultaneously introduce an ordering and then
implement a kind of internalized repetition as they point and count
rhythmically. My kid seems to struggle with the ordering part, and no wonder:
N objects have N! orderings.)

------
wruza
Please note that “counting” there is really “indexing”, as in 1st, 2nd, etc.
Apart from indexing in programming languages, some commenters in this thread
seem to have an idea of counting (indexing) real things from zero, as if it
solved the -1 problem easily. But that is a natural offset between a quantity
and a position. We could in theory rename our ordinals one backwards like:
zeroth, first, second, and so on. But that would shift the meaning
temporarily, and 0th would become new 1st. With new counting in mind, for an
empty set [] count is 0, for [x] count is one and an ordinal for x is
“zeroth”, -1 again dammit.

Between 0 and 10 there is 10 one-sized intervals touching 11
connecting/borderline points (integers). You cannot make this fact go away, no
matter which language you choose.

------
waffletower
If the author had contemplated this sentence before writing this pained and
narrow-minded treatise: "Why thinking should start before writing", engineers
would be slightly more capable of interacting with and designing for other
human beings. Numbering is highly domain specific -- the concept of zero is
not always relevant. And sometimes the lay perspective has primacy over
others. I remember the intense arguments engineers had regarding when the new
millennium was to start. There weren't celebrations on New Year's 2001 that
could compete with the scale of those for the year 2000.

------
tomkaos
Worst than starting at 0 or 1 is two give the option. In old Visual Basic the
"Option Base" statement change the indice for a whole module. I had to debug
code program with a mix use of code with indice starting at 0 and 1.

------
shanxS
I (almost) always fall victim of one-off errors in competitive programming
when working with counting numbers in range. Sticking to convention like 2 ≤ i
< 13, as Dijkstra observed for Mesa programmers, sounds like a good idea.

------
hi41
I need help with this. I intuitively count with starting at one.

In a for loop, if we start with 0, then the terminating condition is i less
than n.

However, ifvit starts at 1, then the terminating condition is i less than or
equal to n.

What mental trick do you use to remember that?

~~~
fctorial
n is n steps ahead of 0,and thats what < checks for.

------
scythe
One thing that’s nice about it is that you can use a positive difference as an
array index directly. This is nice when you want to store a function of the
“distance” between two things, e.g. potential[] = {-10, -5, -3, -2.2, ...};
... potential[r1-r2]. It also works nicely with modular arithmetic as ‘0-_-0
mentions in their post. More generally this corresponds to the array being a
function from the natural numbers to some other values, and this function can
only start at zero if the arrays start at zero. But if you want a function
that starts at 1, you can just set x[0] = invalid().

------
mirekrusin
Nice quote at the end...

"In corporate religions as in others, the heretic must be cast out not because
of the probability that he is wrong but because of the possibility that he is
right." Antony Jay

------
mjw1007
« Exclusion of the lower bound forces for a subsequence starting at the
smallest natural number the lower bound as mentioned into the realm of the
unnatural numbers »

There's a parallel argument for being inclusive in the upper bound: it lets
you specify a range which is the entire size of your integer type.

I can see that that might seem like a poor trade for losing the ability to
represent an empty range starting at zero, but it seems a shame he didn't
mention that this is the tradeoff you're making.

------
transfire
The only reason to count from zero is for the sake of array processing --
given a pointer to an array, the first element will be at pointer plus zero.
That's significant for low-level code as it avoids an extra add one operation.

However for high-level programming, starting at one has advantages. For
instance what index to use to represent insertion of an element at the
beginning? Being able to use zero for this is cognitively easier.

~~~
tabtab
That convention seems confusing to me, especially one new to the convention.
If you need an explicit "insert at the start" operation, then do something
like "x.insertAtStart(y)" instead of "x[0] = y".

~~~
monkpit
This is typically built into a language as “x.unshift(y)”

~~~
tabtab
"unshift" is not very intuitive in my opinion, but let's not get bogged down
with API naming design.

------
ivanhoe
One detail that I always liked about zero-based arrays is that it makes for
loops look nicer, using `i < length` instead of `i <= length`.

------
fctorial
A recent study has found the number of '+1's and '-1's in a codebase is around
15 times higher if you use 1 based indexing.

~~~
crazygringo
I'd love to see the citation?

Also I wonder if it's highly dependent on whether the domain is largely
algorithmic (e.g. video codecs) or business logic (e.g. supply chain).

And how much is simply the language being "misused", e.g. writing "<= n - 1"
rather than "< n".

~~~
fctorial
It was an app I wrote, probably in algorithmic category. But even in business
code, I very rarely see off by one problems that would be easier to handle in
1 based indexing.

> e.g. writing "<= n - 1" rather than "< n"

Wouldn't such errors further increase the ratio?

~~~
crazygringo
I'm sorry, the "recent study" was "an app I wrote"? Sorry, but unless I'm
misunderstanding... that's not a study. And the whole point of a study is to
back up assertions like "I very rarely see" so they aren't just opinion
subject to all the normal human biases we all have.

But if you ran such an analysis across public GitHub repositories per-language
and wrote the results up in a blog post, I'm sure HN would love to see it.
Definitely front-page material.

~~~
fctorial
It wasn't a serious comment. I thought it was obvious from the tone.

> But if you ran such an analysis across public GitHub repositories per-
> language and wrote the results up in a blog post, I'm sure HN would love to
> see it.

I'll see what I can do. I do have some repos in sight that could be used for
it.

But even then this won't be as straightforward as you say since different
languages have different applications (eg cpp for games, julia for scientific
computing). This would require writing the same code in both indexing patterns
and then comparing them.

------
nabla9
While I agree with the conclusion, i think he could have expanded it even
more. Not everyone has as developed aesthetic sense. Measuring, counting,
combinatorics, indexing, arithmetic with ranges.

95% of cases it does not matter or make things more elegant or simple, but
when it does it's always zero-indexing that is more elegant.

~~~
akvadrako
No it doesn’t. One indexed means it equals counting. First person = index 1.

------
jedberg
At the end of the day they are both great and they both suck depending on
context. I use 0 based when programming and 1 based pretty much everywhere
else.

And in both cases I always run into an issue where I think, "This would be so
much easier if we just started at [the other index]".

~~~
mumblemumble
I use 0 based when programming in some languages, and 1 based in others.
Everywhere else I use 1 based.

When I'm programming in 1-based languages, I'm almost always happy with that
choice, because they're almost always languages designed for solving problems
in a domain that were standardized on 1-based counting before Charles Babbage
was born.

When I'm programming in 0-based languages, I'm sometimes very happy with that.
Those times are when I'm working in C or C++ . When I'm using other languages,
I don't care much maybe 1/3 of the time. And the majority of the time I still
wish it were 1-based, because I'm using that language to solve problems in a
domain that had standardized on 1-based counting before Charles Babbage was
born.

------
waynecochran

        Case: indexing an array in ASM, C, C++, Swift,…
        Case: using an offset 
           0 <= i < N
    
        Case: indexing an array in Pascal, Ada, …
        Case: writing a math paper
        Case: talking with a non-programmer
           1 <= i <= N

------
marknadal
No: [https://hackernoon.com/dijkstra-is-wrong-and-so-am-
i-f36e2fb...](https://hackernoon.com/dijkstra-is-wrong-and-so-am-
i-f36e2fbd5ae4)

~~~
pwdisswordfish2
Silly article. Most of its points are actually arguments against JavaScript's
type system and semantics, not zero indexing per se. (Consider how would they
apply if we used letters for indexing, where there's no longer a superficially
appealing zero value to special-case: ‘We should use B-based indexing, because
A is a falsey value in JavaScript! Also, now we can use A to denote missing
elements!’.) Others are empty appeals to vaguely defined ‘mathematics’ that
ultimately boil down to historical legacy.

It is true that most matrix theorems are formulated with 1-based indices. But
mathematical notation is full of unfortunate historical accidents (like
defining π to be _half_ the circumference of the unit circle), so one should
be cautious when drawing inspiration from it. And for what it's worth, set
theorists start ordinal numbers from zero, and each ordinal a half-open
interval of numbers which precede it:

[https://en.m.wikipedia.org/wiki/Ordinal_number#Von_Neumann_d...](https://en.m.wikipedia.org/wiki/Ordinal_number#Von_Neumann_definition_of_ordinals)

------
hghhbvv
Purely functional languages have no reason to 0-indexed arrays. Imperative
languages that deal with for loops are more logically consistent with
0-indexed arrays. I think.

------
jessermeyer
0 is the first number. 1 is the first number 1 unit from 0.

~~~
LanceH
One is the first number. Until there is one of something there is no point to
counting at all. Zero is a regression from one and only significant for the
lack of that something which we started counting at 1.

~~~
baddox
But there absolutely is a point in setting out to count something when it
turns out there is zero of that thing. If you don't know how many of something
there is, but you know that this information is important, you will want to go
out and count. If it's _really_ important, then you will likely want to keep
records of the count every time you perform it. This is, of course, very
important in commerce.

~~~
LanceH
Oops, I was wrong. A count is a quantity.

This is numbering being talked about. Guy finishes a marathon in first place,
he would be the zeroth runner and one runner has finished. Most people would
intuitively like those numbers to line up.

Of course, when you build the natural numbers on a computer and use those as
indices to arrays, it makes sense that the first index is zero. So the first
(common usage) element would then naturally be called the zeroth element.
This, of course, gives you the problem that array.size == x means that
array.last_index == x - 1 and all the off by one errors that entails.

~~~
baddox
Sure, but I don't think anyone's complaining about how you would assign race
completion position labels in a programming language. Surely you would do
something like this:

    
    
        // Start the position at one, because that's how we
        // assign number labels to finishers in a race.
        let position = 1
    
        // Create a callback that will assign a label to
        // each competitor when that competitor finishes
        // the race.
        let assignLabel = (competitor) => {
          competitor.label = position
          position = position + 1
        }
    
        // Begin the race, and pass it a callback that will
        // be run each time a competitor finishes the race
        // (in the order they finish).
        race.begin(assignLabel)
    

Note that this "label" really is just a label. It happens to be an integer
here, but we could also use a library that outputs English strings like
"first", "second", "third", etc. This debate is focused more on how elements
in an ordered collection are _accessed_.

------
cedricbonhomme
In the case of lists/arrays, it's because we count the number of shift. It's
what I always thought. I see analogies with Turing machine.

------
burnte
It does, ask any shepherd, accountant, quartermaster, etc. It has a well
defined meaning and use over the centuries which for hysterical reasons of
economy it took on a second meaning equal to physical 1. Luckily it's the only
case in computing where established meanings in base ten were changed to fit a
base 2 world.

~~~
akvadrako
1 and 0 have the same meaning in both bases

~~~
burnte
CPU0 would disagree, for example. A non technical person might be forgiven for
thinking a system that says CPU0 has no CPUs, when in fact it has one, again,
for example. Many logical objects start their enumeration at zero and
increment from there. There are four rings of operation in Intel CPUs, but
they are labeled ring 0 through 3.

~~~
akvadrako
I’m sorry but you don’t understand what number base means

[https://en.m.wikipedia.org/wiki/Radix](https://en.m.wikipedia.org/wiki/Radix)

Nothing to do with starting number. And base 0/base 1 makes no sense.

~~~
burnte
I'm sorry, but you clearly haven't heard of unary, or base 1, which is
probably the earliest counting system which 1 is 1, 2 is 11, 3 is 111, etc.
Tallymarks. You are correct base 0 would make no sense, however.

But yes please explain to me the very thing we're talking about which is
exactly what I was referencing when pointing out that using 0 as an identifier
rather than a value is moderately counterintuitive.

