Why do we count starting from zero?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
143
down vote

favorite
54












In computer science, we usually count starting from 0. Is there any effective way to explain why, to new programmers who ask why?



I've read a bunch of different sources that list several reasons for 0-indexing. However, they either seem unconvincing, or seem hard to explain to a new programmer who doesn't have much experience with computer science yet:



  • Zero-based indexing lets you write loop conditions as i < n; with one-based indexing, we'd have to write i < n+1, which saves one instruction. This makes no sense to me; i <= n seems like it would be fine.


  • In C, we can use *a to access the first element of array a. This doesn't seem very relevant today for a new student who isn't programming in C.


  • With zero-based indexing, the expression a[i] compiles to an operation on memory address a + c*i where c is a constant representing the size of a single array element; with one-based indexing, it would need to compile to a + c*i - c. This reason seems debatable today (couldn't a modern compiler often optimize this away?), but more importantly, I don't really want to be explaining memory addresses to a new programmer who doesn't understand memory layout and maybe doesn't even understand arrays yet.


Is there a better way to explain why to a new student who is just getting started with computer science?







share|improve this question
















  • 8




    As an extra source of input, have you seen the other question Real life examples of 0-indexing? Might be some help there.
    – Gypsy Spellweaver
    Sep 3 at 2:05







  • 2




    Please avoid adding your answers in the comments. It gets around our quality control systems, for example downvoting and collaborative editing. It also unfairly puts your answer above everyone elses. I've moved these answers-in-comments to chat for posterity. Please avoid adding future answers in the comment section.
    – thesecretmaster♦
    Sep 6 at 1:19











  • Please do not use the comment section to answer the question. I will be periodically deleting all answers-in-comments. Instead, you're welcome to write up your thoughts as an answer, using the form at the bottom of the page.
    – thesecretmaster♦
    2 days ago















up vote
143
down vote

favorite
54












In computer science, we usually count starting from 0. Is there any effective way to explain why, to new programmers who ask why?



I've read a bunch of different sources that list several reasons for 0-indexing. However, they either seem unconvincing, or seem hard to explain to a new programmer who doesn't have much experience with computer science yet:



  • Zero-based indexing lets you write loop conditions as i < n; with one-based indexing, we'd have to write i < n+1, which saves one instruction. This makes no sense to me; i <= n seems like it would be fine.


  • In C, we can use *a to access the first element of array a. This doesn't seem very relevant today for a new student who isn't programming in C.


  • With zero-based indexing, the expression a[i] compiles to an operation on memory address a + c*i where c is a constant representing the size of a single array element; with one-based indexing, it would need to compile to a + c*i - c. This reason seems debatable today (couldn't a modern compiler often optimize this away?), but more importantly, I don't really want to be explaining memory addresses to a new programmer who doesn't understand memory layout and maybe doesn't even understand arrays yet.


Is there a better way to explain why to a new student who is just getting started with computer science?







share|improve this question
















  • 8




    As an extra source of input, have you seen the other question Real life examples of 0-indexing? Might be some help there.
    – Gypsy Spellweaver
    Sep 3 at 2:05







  • 2




    Please avoid adding your answers in the comments. It gets around our quality control systems, for example downvoting and collaborative editing. It also unfairly puts your answer above everyone elses. I've moved these answers-in-comments to chat for posterity. Please avoid adding future answers in the comment section.
    – thesecretmaster♦
    Sep 6 at 1:19











  • Please do not use the comment section to answer the question. I will be periodically deleting all answers-in-comments. Instead, you're welcome to write up your thoughts as an answer, using the form at the bottom of the page.
    – thesecretmaster♦
    2 days ago













up vote
143
down vote

favorite
54









up vote
143
down vote

favorite
54






54





In computer science, we usually count starting from 0. Is there any effective way to explain why, to new programmers who ask why?



I've read a bunch of different sources that list several reasons for 0-indexing. However, they either seem unconvincing, or seem hard to explain to a new programmer who doesn't have much experience with computer science yet:



  • Zero-based indexing lets you write loop conditions as i < n; with one-based indexing, we'd have to write i < n+1, which saves one instruction. This makes no sense to me; i <= n seems like it would be fine.


  • In C, we can use *a to access the first element of array a. This doesn't seem very relevant today for a new student who isn't programming in C.


  • With zero-based indexing, the expression a[i] compiles to an operation on memory address a + c*i where c is a constant representing the size of a single array element; with one-based indexing, it would need to compile to a + c*i - c. This reason seems debatable today (couldn't a modern compiler often optimize this away?), but more importantly, I don't really want to be explaining memory addresses to a new programmer who doesn't understand memory layout and maybe doesn't even understand arrays yet.


Is there a better way to explain why to a new student who is just getting started with computer science?







share|improve this question












In computer science, we usually count starting from 0. Is there any effective way to explain why, to new programmers who ask why?



I've read a bunch of different sources that list several reasons for 0-indexing. However, they either seem unconvincing, or seem hard to explain to a new programmer who doesn't have much experience with computer science yet:



  • Zero-based indexing lets you write loop conditions as i < n; with one-based indexing, we'd have to write i < n+1, which saves one instruction. This makes no sense to me; i <= n seems like it would be fine.


  • In C, we can use *a to access the first element of array a. This doesn't seem very relevant today for a new student who isn't programming in C.


  • With zero-based indexing, the expression a[i] compiles to an operation on memory address a + c*i where c is a constant representing the size of a single array element; with one-based indexing, it would need to compile to a + c*i - c. This reason seems debatable today (couldn't a modern compiler often optimize this away?), but more importantly, I don't really want to be explaining memory addresses to a new programmer who doesn't understand memory layout and maybe doesn't even understand arrays yet.


Is there a better way to explain why to a new student who is just getting started with computer science?









share|improve this question











share|improve this question




share|improve this question










asked Sep 3 at 0:54









D.W.

819245




819245







  • 8




    As an extra source of input, have you seen the other question Real life examples of 0-indexing? Might be some help there.
    – Gypsy Spellweaver
    Sep 3 at 2:05







  • 2




    Please avoid adding your answers in the comments. It gets around our quality control systems, for example downvoting and collaborative editing. It also unfairly puts your answer above everyone elses. I've moved these answers-in-comments to chat for posterity. Please avoid adding future answers in the comment section.
    – thesecretmaster♦
    Sep 6 at 1:19











  • Please do not use the comment section to answer the question. I will be periodically deleting all answers-in-comments. Instead, you're welcome to write up your thoughts as an answer, using the form at the bottom of the page.
    – thesecretmaster♦
    2 days ago













  • 8




    As an extra source of input, have you seen the other question Real life examples of 0-indexing? Might be some help there.
    – Gypsy Spellweaver
    Sep 3 at 2:05







  • 2




    Please avoid adding your answers in the comments. It gets around our quality control systems, for example downvoting and collaborative editing. It also unfairly puts your answer above everyone elses. I've moved these answers-in-comments to chat for posterity. Please avoid adding future answers in the comment section.
    – thesecretmaster♦
    Sep 6 at 1:19











  • Please do not use the comment section to answer the question. I will be periodically deleting all answers-in-comments. Instead, you're welcome to write up your thoughts as an answer, using the form at the bottom of the page.
    – thesecretmaster♦
    2 days ago








8




8




As an extra source of input, have you seen the other question Real life examples of 0-indexing? Might be some help there.
– Gypsy Spellweaver
Sep 3 at 2:05





As an extra source of input, have you seen the other question Real life examples of 0-indexing? Might be some help there.
– Gypsy Spellweaver
Sep 3 at 2:05





2




2




Please avoid adding your answers in the comments. It gets around our quality control systems, for example downvoting and collaborative editing. It also unfairly puts your answer above everyone elses. I've moved these answers-in-comments to chat for posterity. Please avoid adding future answers in the comment section.
– thesecretmaster♦
Sep 6 at 1:19





Please avoid adding your answers in the comments. It gets around our quality control systems, for example downvoting and collaborative editing. It also unfairly puts your answer above everyone elses. I've moved these answers-in-comments to chat for posterity. Please avoid adding future answers in the comment section.
– thesecretmaster♦
Sep 6 at 1:19













Please do not use the comment section to answer the question. I will be periodically deleting all answers-in-comments. Instead, you're welcome to write up your thoughts as an answer, using the form at the bottom of the page.
– thesecretmaster♦
2 days ago





Please do not use the comment section to answer the question. I will be periodically deleting all answers-in-comments. Instead, you're welcome to write up your thoughts as an answer, using the form at the bottom of the page.
– thesecretmaster♦
2 days ago











19 Answers
19






active

oldest

votes

















up vote
184
down vote













None of the reasons you suggest really get to the heart of why we use zero-indexing in CS. Dijkstra's EWD831 explains why this convention works out the best. It comes down to the fact that we want to represent sequences of integers as half-open intervals that are inclusive on the start side.




To denote the subsequence of natural numbers 2, 3, ..., 12 without the pernicious three dots, four conventions are open to us

a) 2 ≤ i < 13

b) 1 < i ≤ 12

c) 2 ≤ i ≤ 12

d) 1 < i < 13




To paraphrase Dijkstra:



  • (a) and (b) have the advantage that subtracting the bounds gives you the length, which is convenient because you don't need to remember to add or subtract 1.

  • (a) and (c) have the advantage that sequences starting with zero don't need a negative lower bound -- and negatives are no longer natural numbers.

  • (a) and (d) have the advantage that if you create an interval that starts with zero and shrink it down to zero-length, you don't need a negative for the upper bound.

Because of the above, we want to write all of our intervals as (a).



Once you accept that (a) is the correct way of specifying intervals, indexing an array of length N as [0, N) is much nicer than [1, N+1).




Two additional notes in favor of using (a) for intervals.



The first point above is important because half-open intervals nicely decompose into other half-open intervals. This makes implementing divide-and-conquer algorithms like merge sort significantly less error prone.



For example:



  • [4, 14) can be broken into the equal-sized intervals [4, 9) and [9, 14), and the middle index is computed as $9 = frac4 + 142$. This is quite clean and nice.

  • [4, 13], decomposes into [4, 8] and [9, 13], where you get the end of one sequence as $8 = frac4 + 13 + 12 - 1$, and the beginning of the next sequence as $9 = frac4 + 13 + 12$. It's easy to forget to add or subtract 1 somewhere.

It's also a bit jarring to specify intervals with (b), because it feels unnatural to skip the first element when you're writing a loop.




As for how to explain the above to your students, I think that they just need to accept that breaking sequences of integers in half is something they'll do later on, and then a few examples will quickly point to [,) intervals and zero indexing as the most natural choice.






share|improve this answer
















  • 6




    The half-intervals decomposing into half-intervals is a nice touch. Dijkstra's explanation does good job of justifying the use of the common scheme within CS as it was becoming a modern science.
    – Gypsy Spellweaver
    Sep 3 at 6:53






  • 20




    Nice contribution and good insight. You've made this corner of the internet a better place :) Welcome to Computer Science Educators. Take a look around, I'd love to know what else you can add.
    – Ben I.♦
    Sep 3 at 12:11






  • 3




    While a good reason to start indexing at 0, it feels much easier and more natural to mentally parse (d) and especially (c) than (a) or (b) - "numbers from x to y" in natural language usually means inclusive of both (or exclusive of both)
    – msam
    Sep 4 at 13:34






  • 2




    @msam: Fully closed or fully open may be "more natural," but the subtraction property of half-open is extremely important. The interval [a, a+b) is exactly b elements long, without any pesky +1 or -1 terms. You simply cannot avoid having +1s and -1s everywhere when you use fully closed or fully open intervals.
    – Kevin
    Sep 5 at 1:30






  • 5




    This also matches the behavior of the modulo operator, the return value of which lies in [0, n). number_of_values_ending_in_a_particular_digit[x % 10] += 1
    – Roman Odaisky
    Sep 5 at 1:48


















up vote
83
down vote













If I can modify the question, I can answer what I believe you are looking for.




The question is "Why do we count starting from zero?" The answer is "we don't" Not even in computer science do we "count" from zero. A list with 15 items in it from outside CS still has 15 items in it inside CS realms. Many languages include a count type function for arrays, and such a function would still return 15 for that list.




If the question becomes "Why do we index from zero?" then it has a different answer. This time the answer is "because that's the way everyone else does it." When we separate the concepts of "indexing" and "counting" things become simpler to explain. Often true of any concept, use the proper terminology and many difficulties are eliminated.




As to why we, as humans, index from zero, while counting from one, only requires a little thought before clarity arrives. Assuming a classroom environment, where the class period lasts for a specified time, perhaps 50 minutes, you can ask at very near, but after, a 60 second mark, how many minutes the class has been in session. If asked at 5:02 minutes into class, the answer will be five minutes. Ask them how long class had been in session five minutes ago, which would be around 0:20 into the class period. The answer should be zero minutes. Once they accept that it was zero minutes, even at 0:59 into the class, you can emphasize that even though the class time had not reached a full minute, it is still class time, and should have some way of "indexing" it. Since the number before one is zero, it must have an index of zero. Hence the "first minute" (by counting) has an index of zero.



The same thought experiments can be conducted with a ruler/tape measure, where the measure starts at zero, and the first centimeter/inch is called, and written, zero. The same concept applies to any distance, such as miles or kilometers, but those are harder to fit into the classroom. In the USA, most highways have "mile markers" that help in locating people for emergency responders. They mark the distance from the beginning of that highway on its south-western end. (The beginning is at the state line if it crosses from one state to another.) "Mile marker" 1 is set after the first mile is completed. "Mile marker" 0 is sometimes seen on the state line, though it is not always there. The first mile, in counting, has an index of 0.



As another example, though not quite as helpful, and requiring that the students have a level of algebra experience to apprehend it, is exponents. Limiting it to non-negative powers of ten and applying it to whole numbers only, we can use the fact that $10^0 = 1$ while $10^1 = 10$. The exponent represents the index for how many places to the right to move (again distance to move) the decimal point, while the count of the digits before the decimal point will be 1 larger.



Final demonstration: "What is the index of the first position on the volume knob below?" "What is the index of the last position on that volume knob?" "How many positions can you count on that volume knob?"



Volume Knob




Once the "index" vs "count" is solved, you can move into the CS realm, where the same practices are followed.



An array is "indexed" from zero and "counted" from one. Why? Because that is the way humans index and count. It certainly comes in handy when doing arithmetic with memory addresses, and there's nothing wrong with taking advantage of things that "just work" naturally. Similar shortcuts include dividing and multiplying by powers of two by shifting bits to the right of left. Its usefulness to the compiler, or the developer, however, is not the why. Such "benefits" are only side effects of "what was" before CS was a reality.



Bottom line is that index from zero and count from one existed a very long time before electronic computers were invented. Like any other science, computer science has to build upon what already exists before inventing new things. Zero-based indexing is one such "per-existing" thing.






share|improve this answer


















  • 6




    You claim we count from 1. But why don't your examples show that we count from 0? Once we have counted the class's first minute, class has been in session a minute -- counting it is not the start of the counting process but the completion of the subtask of counting that minute. This is independent of whether we index it as "0th" or "1st".
    – Rosie F
    Sep 3 at 7:58






  • 17




    I think your answer is in essence just "everywhere we start counting at one, but start indexing at zero - but not a lot of the answer will help children grasping the idea of what an "index" is. - The following task might help "Please paint the first 5cm of this paper red, tell your partner where he should start painting and where he should stop." And he will naturally tell his partner "Paint everything from 0 to 5 red"
    – Falco
    Sep 3 at 11:52






  • 8




    @Bergi No, all respect to Asimov, we shouldn't say "zeroth" mile. That's the difference between counting and indexing. It is the "first" mile, and has an index of "zero". The second mile has an index of one. Until counting and indexing are separated in the individual's mind, such problems will continue to rise.
    – Gypsy Spellweaver
    Sep 3 at 17:09






  • 6




    @Barmar: Yes, there are many places where buildings have a floor 0, though it is typically called the "ground floor" and labelled "G" on elevator buttons. Unlike North America, where the ground floor is floor 1 and one storey up is floor 2, in Europe, the UK, and Australia the convention is that the ground floor is 0 and one storey up is floor 1.
    – user128216
    Sep 3 at 23:18







  • 17




    Perhaps rather than rulers and road markers, you could ask the students to think about why it's best to say a new born baby is 0 not 1.
    – curiousdannii
    Sep 4 at 10:28

















up vote
46
down vote













I'm surprised that the following hasn't been stated yet. All of the answers given so far seem to be "after the fact" explanations of something that is really based on the way people built most (not all) early computers as binary machines.



To make things a bit more compact here, I'll assume we are creating a 4 bit (nibble) based machine. We don't want to use more binary components to build a nibble than we need to because we are cheap, so we use four bi-stable components (relays, vacuum tubes, transistors). We think of (perhaps) the two states as zero and one rather than, say, red and green.



So we have (0000) through (1111) as the combinations of the four transistors of a nibble. We can interpret them any way that we like. Suppose we want to interpret them as integers. How shall we assign the different codes to integers. We could let (0000) represent 42, a fundamental universal constant, and (0001) represent 3, an approximation to pi and so on, but we realize pretty soon that any computations we want to do with such an encoding would be pretty complex - and complexity in a machine costs money. We are cheap, remember.



So we notice that the codings are actually binary numbers. Well almost nobody used binary numbers before this so we start to think about it seriously now, as they have an application. I note that some early computers were actually decimal, not binary, but they recognized that while convenient it wasn't cheap.



Now, using binary numbers, not just binary encoding, it becomes "obvious" that the codes represent zero through fifteen, not one through sixteen. Using (0000) to represent 1 just seems dumb at this level - and at this time.



Now, (bit later) we want to index an "array" of nibbles. How shall we do it. Well we assign index numbers to the individual cells. Suppose we have four such cells. How shall we do it? We could use (0001) through (0100) to index them (1 through 4), but now (a-ha) if we have sixteen nibbles to index but start with one we can only get (our count) to fifteen without using another nibble or letting (0000) represent the last (sixteenth) cell. That seems dumb, so we (a-ha) index from zero. Now we can index sixteen cells with sixteen codes and it is cheap and pretty natural. The only cost is a bit of confusion in the minds of beginning programmers, but others will pay those costs and our machines can be cheap.



No contest. Index from zero.



The other answers here explore why the arithmetic inside the machine is cheap this way, so I won't repeat it here. But note that all of this happened before any languages at all were invented other than the simplest of machine coding without any abstraction facilities at all. It was just economics and engineering. Make it simple, keep it cheap.






share|improve this answer


















  • 4




    Give your students this simple task and they will find the answer themselves: Number these ten students, each with a unique number, but you can only use a single digit - they will quickly come up with the solution to number then 0 to 9 - and that is why we index starting at zero, we don't like waste :-)
    – Falco
    Sep 3 at 11:46






  • 12




    Interestingly, all the early languages have one-based (or user-defined) indexing (e.g. Fortran (1957), Algol (1958)), or don't have a notion of "array" at all (Lisp (1957)). Zero-based indexing is a rather modern invention.
    – Jörg W Mittag
    Sep 3 at 14:51






  • 7




    Interesting that on rotary telephones 0 (with ten pulses) comes after 9, but then pulsing the line zero times doesn't really work physically.
    – Scott Rowe
    Sep 3 at 17:36






  • 5




    @JörgWMittag: Interesting! I wonder if designers of early languages were thinking that anyone who knew how computers and binary numbers really worked would just write in assembly language. Early computers were slow, and early compilers presumably didn't optimize well / at all. Anyway, this answer is exactly what occurred to me, too: letting an N-bit index address a full 2^N elements. Power-of-2 buffer/object sizes are a big deal.
    – Peter Cordes
    Sep 4 at 0:01






  • 5




    @ScottRowe zero had 11 pulses, and one had 2 pulses. This was to stop the equipment reacting to random single pulses.
    – ctrl-alt-delor
    Sep 4 at 8:09

















up vote
32
down vote













You have already gotten several good answers about why zero-based indexing is useful, and you have been explained the difference between indexing and counting.



I now want to challenge the basic premise of your question: it is not, in fact, universally agreed-upon that indexing starts at zero.



In Excel, which is arguably the most widely-used programming language in the world (even though it doesn't look much like a "traditional" programming language), row-indexing starts at 1 and not 0, and column-indexing starts at A and not ε.



In Visual Basic, the programmer can choose between zero-based and one-based indexing as the default indexing on a per-module (per-file) basis with the Option Base declaration. Plus, the programmer can declare the exact index range for each individual array using the To keyword in the array declaration, e.g.:



Dim Count(100 to 500) as Integer


This declares an array of integers named Count with indices ranging from 100 to 500 (inclusive).



In the "Wirthian languages", i.e. Pascal and all its successors (Modula-2, Oberon, Component Pascal), arrays can be indexed by any arbitrary range of scalars (except reals).



type
foo = array[-10 .. 10] of real;
(* an array of reals with indices ranging from -10 to +10 *)

bar = array['b' .. 'g'] of 100..200;
(* an array of integers from 100 to 200 with indices ranging from 'b' to 'g' *)

weekday = (monday, tuesday, wednesday, thursday, friday, saturday, sunday);
baz = array[tuesday..friday] of boolean;
(* an array of booleans with indices ranging from tuesday to friday *)


The Wirthian languages, in turn, inherited this from ALGOL-60 and ALGOL-68.



Ada is similar, any discrete type can be used as the index type. Interestingly, idiomatic Ada style suggests using a range starting from 1 and not 0 when using an integer range as indices.



In Eiffel, which is heavily inspired by Wirthian languages, array indices have explicit lower and upper bounds which can be any signed 32-bit integer, so you could have an array with indices ranging from -1000000 to -1, for example.



In Fortran, the default is to start at 1, but like ALGOL, Pascal, Eiffel, and VB, you can specify any arbitrary lower and upper bound.



In Matlab, indexing starts at 1. In APL and Perl, you can choose.



Even in the "real world", there are different schemes. E.g., in Germany, the ground floor, i.e. the floor you enter from street level is called "ground floor", and is usually labelled 0 on elevator buttons that use numbers ("EG" if using letters). The floors above ground level are called "1st upper floor" (and so on) and labelled 1, 2, etc. (or "OG 1", …) The floors below ground level are called "1st lower floor" (and so on) and numbered -1, -2, etc. (or "UG 1", …)



In the US, "1st floor" is the floor at ground level.



Apparently, in Barcelona, there is a "ground floor", a "primary floor", and then the "first floor" is two stairs up from ground level.



There is an interesting discussion about this on the Wiki: http://wiki.c2.com/?ZeroAndOneBasedIndexes



I also found an essay that compares the syntactic and semantic noise of typical tasks using many different indexing schemes: http://enchantia.com/graphapp/doc/tech/arrays1.html






share|improve this answer
















  • 1




    It would seem that in Barcelona the "first floor" is one floor above the "primary floor", which name suggest that it is the "origin" for the building's life. The "ground floor" is presumably where garage, storage, utilities, and other facilities exist while regular rooms (kitchen etc.) are on the primary floor. Servants' quarters, are also likely to be "below" the primary floor. The ground floor would, presumably, have an index of -1.
    – Gypsy Spellweaver
    Sep 3 at 17:41






  • 2




    In one university I have visited, the floor numbers were in feet above sea level. So not even consecutive. (This is also discussed here cseducators.stackexchange.com/a/215/204 )
    – ctrl-alt-delor
    Sep 4 at 8:19






  • 4




    The reason for the numbering of floors in Barcelona is due to an old building regulation which dictated no buildings could have more than six floors. To work around this restriction, extra floor names were added so that the maximum numbered floor was always #6. The extra floor names are "Entresuelo" and "Principal" just above the ground floor, and "Atico" and "Sobreatico" just above the sixth floor. (Not all buildings will have all of these floor names).
    – Aaron F
    Sep 4 at 12:20






  • 2




    Nothing Wirthian is inherited from ALGOL-68.
    – philipxy
    Sep 6 at 2:35






  • 2




    +1, but this is only half the answer. The other half is that in the 70's C made the choice to directly support only indexing arrays from 0, as this made the compiler simplest (which was really C's primary design goal). Because C compilers were so simple, they were easy to make and put on any machine, and as a result of this and a few other bits of historical luck, C became super popular. As a result of that, a whole host of other languages took their lead from C.
    – T.E.D.
    Sep 6 at 14:32

















up vote
18
down vote













When I've explained this to beginning students, I don't stray far from your third reason, though I agree that the beginning of arrays is early to introduce the concept of memory addresses. Among other things, that invites about your variable, c, when the only variable they need to worry about is i.



Instead of memory addresses, I talk about distances from the start. I've given a sample below using paper and a pencil as a reference point, though in my classroom I use the whiteboard and hold a marker. All of the numbers are in little boxes, and together they form a rectangle.




Look at the list of numbers on the paper. We all know about ordinal numbers, "first", "second", "third", and so forth. But when we program, we actually refer to the list numbers a slightly different way, as 0, 1, and 2. This is called 0-based indexing, and the reasons for it don't matter right now. What matters is that the first item on the list is actually item 0.



Honestly, that's all you need to know to use arrays correctly. But if you want a hint about why we actually do this, you can think about zero-based indexing as the distance from the head of the array.



So, if I'm at the head of the array, how many moves do I have to make to read the first number? No moves, I'm already there. What about the second number? I make one move to get there. The fourth number? One, two, three moves.



Beyond the most important fact that we start counting from 0, thinking about it as "moves" is actually a good way to think about array indexes, because when we come back to this topic later, you'll see that the distance from the head turns out to be an important concept for understanding a lot of things a computer does. Don't worry we'll get there soon enough.



So, for now, what is the index for this spot in the array? (I point to a random index, wait for the students to arrive at the answer.) Good, well done. Now, moving on to ...







share|improve this answer






















  • 'cardinal numbers, "first", "second", "third"'. These are ordinals, not cardinals. Cardinals count amount. Ordinals count order.
    – Potato44
    Sep 3 at 12:43










  • @Potato44 Yes, they are. What an embarrassing error! Thanks for pointing it out, I'll fix it now.
    – Ben I.♦
    Sep 3 at 14:49






  • 2




    Ah, but some of us are willing to say zero-th, also.
    – Buffy
    Sep 3 at 14:54

















up vote
9
down vote














In computer science, we usually count starting from 0.




In programming or in (theoretical) computer science?



In Programming



In C programming language you count from 0 to (N-1). And of course in languages which are influenced by C: Java, JavaScript, PHP, C#, C++...



You already named the reason for this:




In C, we can use *a to access the first element of array a.




... and because a[i] is the same as *(a+i) the first index of the array must have the index 0.




This doesn't seem very relevant today for a new student who isn't programming in C.




In many (most?) other programming languages (Basic, Pascal and Matlab for example) you typically count from 1 to N, not from 0 to (N-1).



(For example in for loops.)



As already said in the other answers there often is the possibility to define the index of the first element of an array freely (e.g. in Pascal) or the index of the first element is even fixed to 1 (e.g. in Matlab).



These languages don't have pointer arithmetic.



In (theoretical) computer science



I have no idea if they count from 0 there.



However I think that the programming languages which are used most influence the way of thinking in theoretical computer science, too.






share|improve this answer


















  • 1




    I think the C equivalence of arr[i] = *(arr+i) follows from its choice of zero-based indexing, not the other way around. But good point that having pointer arithmetic at all makes zero-based indexing much more natural, and that most still-used languages with 1-based indexing don't have that. C started as a portable assembly language, so it's totally natural that it works like asm in this regard.
    – Peter Cordes
    Sep 4 at 0:04







  • 1




    @PeterCordes I'm not sure. But I think the fact that the array operator can be used for pointer arithmetic at all (such as ptr[-5]) played a role in defining that ptr[i] is equal to *(ptr+i).
    – Martin Rosenau
    Sep 4 at 5:53






  • 3




    The advantage of zero-based indexing becomes even more apparent when you need to map a 2D matrix to a linear array.
    – 200_success
    Sep 4 at 18:13






  • 1




    This is the missing half of Jorg's answer, which together make the correct answer. C made the choice to only support indexing arrays from 0, and after it became popular it influenced the design of a lot of other languages. However, its quite likely most languages don't force a 0-based index, and some people thinking this is a computer language thing, (or worse yet, a Computer Science thing) is nothing more than myopia.
    – T.E.D.
    Sep 6 at 14:37










  • Most index from 0, including BASIC (though I'm sure there's a variant which starts at 1). Here's a table.
    – Schwern
    3 hours ago

















up vote
8
down vote













In languages such as C, the first item in an array has an offset of zero from the pointer. If the size of your objects are 4 bytes, the next item has an offset of 1 x 4 bytes.



Index Size Offset
0 4 base + 0
1 4 base + 4
2 4 base + 8
3 4 base + 12


And so on.



If the items were indexed on natural counting, there would have to be an adjustment made by both the computer and the programmer to find the location of the item in memory. Mistakes would be made by having this additional step, particularly on the human side of the process. It's easier, although slightly unintuitive, to use zero-based indexing.






share|improve this answer
















  • 3




    Welcome to Computer Science Educators! Isn't this just a restatement of OP's third bullet?
    – Ben I.♦
    Sep 3 at 12:16










  • yes, the pointer (which is the array) contains the 1st element, then you add 1 to get the next element etc. In assembler we were taught indexing to access arrays, so moving to C it all made simple sense.
    – WendyG
    Sep 3 at 12:17






  • 1




    @BenI. My answer addresses the human side of "making it easy".
    – CJ Dennis
    Sep 3 at 12:20










  • Welcome to the community, please read the question. The OP states in the question that this explanation is unsatisfactory, for the intended audience.
    – ctrl-alt-delor
    Sep 4 at 7:58










  • Keep in mind that C arrays are rather plain. In many languages, the pointer refers not to the first item, but to things such as the length of the array. And yet both 0-indexed and 1-indexed arrays exist. Indeed, you could use your argument to argue that arrays should start at 1, because that would allow you to store metadata in the "0 offset".
    – Luaan
    Sep 5 at 9:05

















up vote
6
down vote













Simply put, we do not count from zero, we shift from zero



You can think C as a neat way to not write different assembly for every architecture/machine/processor in existence. Instead, take a simple and short macro-like language for a abstracted machine, compile that, and brk() your way on abstracted memory.



But abstracted memory is only a sequence of bytes, you need a way to refer to specific segments. Enter pointers. But to not make every item a allocation (think of a string where every char is separately allocated) the next step is "lists". The most compact list1 is a pointer to the first element, and then put every other element in adjacent slots.



Every element is, then, indexed as shift from first. And because that, the shift index starts from zero.




1 This is from a era when you need entire reunions to decide if is worth spend whooping 52 bytes to have your system know about leap years...






share|improve this answer





























    up vote
    5
    down vote













    I will try to answer, without reference to low-level programming (or any programming language), without mention of history, or much maths.



    As already stated in some answers, we do not count from zero (using the value 0 to represent 1, and 1 to represent 2 (Usually)). So what do we do?



    We measure from zero. If I give you a ruler, and ask you to measure something, you measure from zero. If I ask you to tell me how far a cell in an array is from the start, then you measure from zero (the first cell is zero from the start: it is at the start), the 2nd cell is 1 from the start.






    share|improve this answer


















    • 3




      We absolutely count from zero. If you want to count sheep hopping over a fence, you initialize the sheep_count variable to 0, not 1. If no sheep appear, you must report that zero value as the count.
      – Kaz
      Sep 6 at 0:03


















    up vote
    4
    down vote













    From time to time I have had to do numerical work in MATLAB and the 1-based indexing always stuck out like a sore thumb, so I have a few examples I can provide where 0-based indexing is advantageous.



    Modular access



    This is the simplest example. If you want to "wrap around" an array, the modulus operator works like a charm. (And don't say "what if the modulus operator were defined from 1 to n instead"—that would be mathematically ludicrous.)



    str = "This is the song that never ends... "
    position = 300
    charAtPosition = str[position % (str.length)]


    Real world examples of this might include working with days of the week, generating repeating gradients, or coming up with a predicable item from a small list given a large ID number.



    Discretisation



    Let's say you want to generate a histogram of heights. The first "bucket" is 50cm-70cm. The next is 70-90cm. And so on up to 210cm.



    Using zero-based indexing, the code looks like



    bucket[floor((height - 50) / 20)] += 1


    With 1-based indexing, it looks like



    bucket[ceil((height - 50) / 20)] += 1
    or
    bucket[floor((height - 50) / 20) + 1] += 1


    (the two have slightly different semantics). So you can either have a stray "+ 1" or use the ceil function. I believe the floor function is more "natural" than the ceil function since floor(a/b) is the quotient when you divide a by b; for this reason integer division often suffices in such calculations whereas the ceil version would be more complex. Also, if you wanted the buckets in reverse order, this is 0-based indexing:



    BUCKETS = (210 - 50) / 20 - 1

    #intuitive because BUCKETS - 1 is the highest index
    bucket[(BUCKETS - 1) - floor((height - 50) / 20)] += 1


    versus



    #not intuitive... what does BUCKETS + 1 represent?
    bucket[BUCKETS + 1 - ceil((height - 50) / 20)] += 1
    or
    #not intuitive... how come a forwards list needs "+ 1" but
    #backwards list doesn't?
    bucket[BUCKETS - floor((height - 50) / 20)] += 1


    Change of Coordinate Systems



    This is related to the above "direction flip". Although I will use a 1 dimensional example, this also applies to 2D and higher dimensional translations, rotations, and scaling.



    Let's suppose, for each slot in the top row you want to find find the best fitting slot in the bottom row. (This often occurs when you want to efficiently reduce the quality of some data; image resizing is a 2D version of this).



    With 0-based indexing:



    0-based indexing



    #intuitive because the centre of slot[0] is actually at x co-ordinate 0.5
    nearest = floor((original + 0.5) / 5 * 7);


    With 1-based indexing:



    enter image description here



    #Why -0.5? Can you explain? And then we need to "fix" it with a +1
    nearest = floor((original - 0.5) / 5 * 7) + 1;


    Nice Invariants



    In order to prove that programs work correctly, computer scientists use the concept of an "invariant"—a property that is guaranteed to be true at a certain place in the code, no matter the program flow up to that point.



    This is not just a theoretical concept. Even if invariants are not explicitly provided, code that has nice invariants tends to be easier to think about and explain to others.



    Now, when writing 0-based loops, they often have an invariant that relates a variable to how many items have been processed. E.g.



    i = 0

    #invariant: i contains the number of characters collected

    while not endOfInput() and i < 10:

    # invariant: i contains the number of characters collected

    input[i] = getChar()

    # (invariant temporarily broken)

    i += 1

    #invariant: i contains the number of characters collected

    #invariant: i contains the number of characters collected


    There are two basic ways to write the same loop with 1-based indexing:



    i = 1
    while not endOfInput() and i <= 10:
    input[i] = getChar()
    i += 1


    In this case i does not represent the number of characters collected, so the invariant is a bit messier. (You would have to remember to subtract one later on if you wanted the count.) Here is the other way:



    i = 0
    while not endOfInput() and i < 10:
    i += 1
    input[i] = getChar()


    Now the invariant holds again so this approach seems preferable, but it seems odd that the initial value of i can't be used as an array index—that we are not "ready to go" straight away and have to fix up i first. I suppose it's initially odd for learners of zero-based languages that, after the loop terminates, the variable is one more than the highest index used, but it all follows from the basic rule of "a list of size i can be indexed from 0 to i-1".



    I admit that these arguments may not be very strong. That said, off-by-1 errors are one of the most common types of bug and at least in my experience, starting arrays from 1 needs a whole lot more adding and subtracting 1 than 0-based arrays.






    share|improve this answer






















    • +1 for the modulus operation argument. I also really like the nice invariants one. I always make a point of explaining to my team the importance of "least surprise" in designing and implementing new features (both in terms of UX design and code design). I feel the two concepts share commonality in that one of the aims of least surprise design is to preserve a high quantity of nice invariants!
      – oliver-clare
      2 days ago

















    up vote
    2
    down vote













    I think that one of the first programming languages to use zero-based indexing was BCPL. In BCPL, pointers and integers are interchangable, and arrays are represented by pointers. Subscripting uses the operator !, so you can get the first and second members of an array using A!0 or A!1. These are defined to be equivalent to !(A+0) and !(A+1) where the unary ! operator dereferences a pointer. It's neat, simple, and consistent, and it wouldn't work with 1-based addressing.



    A lot of BCPL ideas were carried into C, and the rest is history.



    But although zero-based indexing seems to work best for system programming languages, there are many modern languages that chose to start at 1. XPath is an obvious example. I think the rationale there was that it was expected to be used by non-programmers (e.g document authors) and you can't expect a document author to think of the first chapter in a book as chapter 0.






    share|improve this answer




















    • Indeed BCPL seems to be origin of 0-based indexing. We can try to explain to ourselves or to pupils why indexing starts from 0, but the fact is that it only does so in certain languages, and that most of those do so out of historical reasons. This blog shines some light on the origin of 0-indexing: exple.tive.org/blarg/2013/10/22/citation-needed
      – idrougge
      Sep 6 at 12:37











    • Nice blog article. I'm amused by the notion that we're more likely to have heard of Eben Upton than of Martin Richards.
      – Michael Kay
      Sep 6 at 13:31










    • ... It reflects that the author is clearly digging into software history for the first time and is suprised by his discoveries, thinking that perhaps no-one else knows this. However, his conclusions are a bit inconsistent. Zero based indexing in BCPL was an inevitable consequence of having pointers rather than arrays as the fundamental data structuring concept, it wasn't to make array indexing more efficient.
      – Michael Kay
      Sep 6 at 13:38










    • Since we're on Computer Science Educators, I might mention that Martin Richards and Steve Bourne between them probably taught me everything I really needed to know about programming -- mainly by example; they both wrote beautiful code.
      – Michael Kay
      Sep 6 at 13:42

















    up vote
    2
    down vote













    Slight generalization of CJ Denis's answer: The advantage of zero-based indexing is apparent as soon as you start working with relative indices. If you have a base array A and over it, let's say, a sliding window W, you would have to subtract 1 each time you add W-based index to the A-based one.






    share|improve this answer



























      up vote
      2
      down vote













      Why not?



      Why not count from zero? (This answer is a bit like Buffy's answer, but a bit simpler logic than many of the other answers.) Zero is a perfectly valid number. So why not use it? Failing to use that available number is just a waste of the possibility of using that number. You wouldn't want to start lower, since negative numbers may be a bit more complicated to need to consider, and may even be unavailable (when using unsigned numbers). But zero is available, so why waste the possibility of being able to use that number?



      If you do that, it's like the 63 SPT (sectors per track/head) limit that contributed to the 504 MiB / 528 MB) Barrier. That used a 1-based count. If a zero-based count were used, a limit would have been 512 MB instead of 504 MB. In a day and age when hard drives were counted in megabytes, that limit was nearly 1.6% smaller because someone decided to do a one-based count for one of the numbers. So, keeping that real-world actual cost in mind, what benefit is there to trying to exclude zero? If there isn't one, then don't do it.



      Standardizing on one number is nice. When I was ten years old, I knew how to program. Sometimes I counted from one (e.g., "for(x=1;x<=10;x++)" ), while other times I counted from zero (e.g., "for(x=0;x<10;x++)" ). Sometimes I would mix up those methods, and create a fencepost bug (using "for(x=0;x<=10;x++)" ). Later in life, I was pretty strongly compelled to count from zero and drop the test for equality (just testing for inequality using <, instead of "less-than-or-equal" using <=), and once I got into a standardized habit, I found myself to be far less likely to be making those off-by-one errors.



      Ultimately, the code of in many "high level" programming languages is just meant to be converted into "low level" assembly language, which is designed to operate the same way as an actual chip. Zero is kind of a special number (having unique properties with addition and multiplication), while one has less special behavior (having a similar unique property with multiplication, but not addition). So it makes a bit of sense for zero to be special.



      Also, if you think of the "what's left", zero is more logical. If you count down ("'for x=10;x;x--)`"), then do you want to exit when there is one job left, or zero jobs left? Zero is more sensible in that particular case, and that may be a key reason why some of the Intel Assembly Language operators perform the way they do.






      share|improve this answer



























        up vote
        1
        down vote













        I think it's best to view addresses and indices not as identifying objects or elements, but rather the spaces between or on either side of them. Thus, an array with four elements would have the following indices:



        Addr: Base+0 Base+1 Base+2 Base+3 Base+4
        . V V V V V
        Indices: 0 1 2 3 4
        Elements [FIRST] [SECOND] [THIRD] [FOURTH]


        Each element is associated with two addresses--the one immediately preceding it and the one immediately following it. The address immediately following any element other than the last will immediately precede another element, and likewise the address immediately preceding any element other than the first will follow another element. Even though each address other than the first and last will be associated with two elements (one preceding and one following), by convention applying the * operator to an address yields the one following.



        Note that unlike the "half-open interval" view, this approach does not require any special handling for pointers that go one beyond the last element. The address "Base+4" above is associated with the four-element array just like any other, but the * operator cannot be applied to it because that operator would require the ability to compute the next address.






        share|improve this answer




















        • I like this. This is also a useful way of thinking about labels in assembly language (as zero-width). Addresses and labels don't have any natural width associated with them; that depends on what type of load/store you do. (The type system in most languages associates an element width with a pointer, but this is why you can't add/subtract void* in C.)
          – Peter Cordes
          Sep 5 at 1:54


















        up vote
        1
        down vote













        There are many answers but I miss an attempt to make it short and comprehensible for non programmers.




        I don't really want to be explaining memory addresses to a new programmer who doesn't understand memory layout and maybe doesn't even understand arrays yet.




        A simple and short example.

        We have a list of elements aligned one after the other. The start of this list, the first element is flagged with a pin.

        To get the first element, we go to where the pin is.

        To get the second element, we need to go to the pin plus one element.

        Starting at zero the computer can simply calculate where to go from the start location.



        More thoughts on that.

        Counting starts with "one" for the first element. Even for programmers. But programmers don't count elements when they start at zero, they give them names. These names start at the first number that can be built with digits. Zero denotes "nothing" but is the first valid number.




        couldn't a modern compiler often optimize this away?




        I think it can't. How? The calculation described above is fundamental, the CPU does it like that. A compiler can't optimize necessary calculations away.






        share|improve this answer








        New contributor




        puck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.
























          up vote
          0
          down vote













          Languages which start from 0 are currently popular but there are others which start from 1. These examples are quite old. Many of the start from 0 languages are derived from or inspired by C.



          Cobol is not fashionable now but it is still an important language in business and its arrays start at 1. RPG (not role playing games) also has arrays which start from 1. RPG is ugly and horrible but it is also popular in business. My Fortran is rather rusty but I think that it also started at 1. Very long ago, I used Algol and you could choose the starting index 0, 1, or even negative. For some applications, negative indexes e.g. from -10 to +10, were convenient. I am not sure whether this was a standard feature or just one of the dialect that I used. Things were not so standardised back then.



          Edited to remove possible unintended offence.






          share|improve this answer










          New contributor




          badjohn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.
























            up vote
            0
            down vote













            Counting is always 100% arbitrary. Counting from 0, from 1 and from 7 - all make exactly same sense. Our reliance on indexing from 1 in real life is no different than our reliance on 10 as base of positional system. It's nothing but a convention.



            The only issue is "How do I remember where do we agreed to start counting at?". From there comes the lead-on question: "What is the default value for integer variable?" or "If you started with a freshly initialized integer, what would you think would be it's value?"



            And this is the reason why we start at 0: Integers start at 0, so it's helpful to map the first entry of an array to the first value of a variable capable of indexing it.






            share|improve this answer



























              up vote
              0
              down vote













              You give the answer yourself in the third bullet point, and you dismiss it too easily.



              Let me delve into my personal experience from when I learned C in the mid-1980s. I remember when for the first I time saw 68k assembler code produced from indexing an array in C and realized that variables are just constant addresses, and indices are just offsets to them, so that addressing an array element a[i] could be understood as *(a+i) which simply was a readily available adressing mode in machine code if address a was already in a register.



              It was a revelation on many levels: What C is (a macro assembler with a few bells and whistles plus standard library), what a compiler does, under what constraints programming languages work, and why C was so fast.



              Why do you want to deprive your students of this insight? I think teaching arrays (or any programming, really) benefits tremendously from teaching memory addresses and some rudimentary assembler, so just go for it. All language abstraction is operating under the constraints of the metal. Your students will never understand why certain seemingly simple things are expensive or impossible if they don't know what they are actually doing.1



              To sum up, essentially your third bullet point is the reason for the decision by the designers of C (or probably rather, BCPL or B) to start indexing at 0. Saving a subtraction at each element access, i.e. in many hot loops, was certainly highly relvant in 1970. True, today these original reasons are largely irrelevant; but today we have 45 years of code and a diverse C-rooted language tree. Regarding these languages we are locked in for good. As Jörg correctly mentioned in another answer, the decision was made differently for many other languages, probably not coincidentally some for which speed is secondary and some who target a lay audience.



              1Don't get me wrong, I like abstraction. Having had the glimpse under the hood lets me actually appreciate the saftey, correctness and comfort provided by high-level languages and libraries.




              share|improve this answer





























                up vote
                -3
                down vote













                "Thing zero"



                I have nothing, I have one thing, I have two things...



                0,1,2...



                0x00, 0x01, 0x02...



                0000, 0001, 0010...



                There is nothing in my register, there is one thing in my register, there are two things in my register.



                There is nothing in my array, there is one thing in my array, there are two things in my array.



                If you started at one, you'd always have a minimum of one thing.






                share|improve this answer








                New contributor




                Munkee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.













                • 5




                  But myint[0] isn't nothing, it's something.
                  – Ben I.♦
                  2 days ago











                Your Answer




                StackExchange.ifUsing("editor", function ()
                return StackExchange.using("mathjaxEditing", function ()
                StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
                StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
                );
                );
                , "mathjax-editing");

                StackExchange.ready(function()
                var channelOptions =
                tags: "".split(" "),
                id: "678"
                ;
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function()
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled)
                StackExchange.using("snippets", function()
                createEditor();
                );

                else
                createEditor();

                );

                function createEditor()
                StackExchange.prepareEditor(
                heartbeatType: 'answer',
                convertImagesToLinks: false,
                noModals: false,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: null,
                bindNavPrevention: true,
                postfix: "",
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                );



                );













                 

                draft saved


                draft discarded


















                StackExchange.ready(
                function ()
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcseducators.stackexchange.com%2fquestions%2f5023%2fwhy-do-we-count-starting-from-zero%23new-answer', 'question_page');

                );

                Post as a guest






























                19 Answers
                19






                active

                oldest

                votes








                19 Answers
                19






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes








                up vote
                184
                down vote













                None of the reasons you suggest really get to the heart of why we use zero-indexing in CS. Dijkstra's EWD831 explains why this convention works out the best. It comes down to the fact that we want to represent sequences of integers as half-open intervals that are inclusive on the start side.




                To denote the subsequence of natural numbers 2, 3, ..., 12 without the pernicious three dots, four conventions are open to us

                a) 2 ≤ i < 13

                b) 1 < i ≤ 12

                c) 2 ≤ i ≤ 12

                d) 1 < i < 13




                To paraphrase Dijkstra:



                • (a) and (b) have the advantage that subtracting the bounds gives you the length, which is convenient because you don't need to remember to add or subtract 1.

                • (a) and (c) have the advantage that sequences starting with zero don't need a negative lower bound -- and negatives are no longer natural numbers.

                • (a) and (d) have the advantage that if you create an interval that starts with zero and shrink it down to zero-length, you don't need a negative for the upper bound.

                Because of the above, we want to write all of our intervals as (a).



                Once you accept that (a) is the correct way of specifying intervals, indexing an array of length N as [0, N) is much nicer than [1, N+1).




                Two additional notes in favor of using (a) for intervals.



                The first point above is important because half-open intervals nicely decompose into other half-open intervals. This makes implementing divide-and-conquer algorithms like merge sort significantly less error prone.



                For example:



                • [4, 14) can be broken into the equal-sized intervals [4, 9) and [9, 14), and the middle index is computed as $9 = frac4 + 142$. This is quite clean and nice.

                • [4, 13], decomposes into [4, 8] and [9, 13], where you get the end of one sequence as $8 = frac4 + 13 + 12 - 1$, and the beginning of the next sequence as $9 = frac4 + 13 + 12$. It's easy to forget to add or subtract 1 somewhere.

                It's also a bit jarring to specify intervals with (b), because it feels unnatural to skip the first element when you're writing a loop.




                As for how to explain the above to your students, I think that they just need to accept that breaking sequences of integers in half is something they'll do later on, and then a few examples will quickly point to [,) intervals and zero indexing as the most natural choice.






                share|improve this answer
















                • 6




                  The half-intervals decomposing into half-intervals is a nice touch. Dijkstra's explanation does good job of justifying the use of the common scheme within CS as it was becoming a modern science.
                  – Gypsy Spellweaver
                  Sep 3 at 6:53






                • 20




                  Nice contribution and good insight. You've made this corner of the internet a better place :) Welcome to Computer Science Educators. Take a look around, I'd love to know what else you can add.
                  – Ben I.♦
                  Sep 3 at 12:11






                • 3




                  While a good reason to start indexing at 0, it feels much easier and more natural to mentally parse (d) and especially (c) than (a) or (b) - "numbers from x to y" in natural language usually means inclusive of both (or exclusive of both)
                  – msam
                  Sep 4 at 13:34






                • 2




                  @msam: Fully closed or fully open may be "more natural," but the subtraction property of half-open is extremely important. The interval [a, a+b) is exactly b elements long, without any pesky +1 or -1 terms. You simply cannot avoid having +1s and -1s everywhere when you use fully closed or fully open intervals.
                  – Kevin
                  Sep 5 at 1:30






                • 5




                  This also matches the behavior of the modulo operator, the return value of which lies in [0, n). number_of_values_ending_in_a_particular_digit[x % 10] += 1
                  – Roman Odaisky
                  Sep 5 at 1:48















                up vote
                184
                down vote













                None of the reasons you suggest really get to the heart of why we use zero-indexing in CS. Dijkstra's EWD831 explains why this convention works out the best. It comes down to the fact that we want to represent sequences of integers as half-open intervals that are inclusive on the start side.




                To denote the subsequence of natural numbers 2, 3, ..., 12 without the pernicious three dots, four conventions are open to us

                a) 2 ≤ i < 13

                b) 1 < i ≤ 12

                c) 2 ≤ i ≤ 12

                d) 1 < i < 13




                To paraphrase Dijkstra:



                • (a) and (b) have the advantage that subtracting the bounds gives you the length, which is convenient because you don't need to remember to add or subtract 1.

                • (a) and (c) have the advantage that sequences starting with zero don't need a negative lower bound -- and negatives are no longer natural numbers.

                • (a) and (d) have the advantage that if you create an interval that starts with zero and shrink it down to zero-length, you don't need a negative for the upper bound.

                Because of the above, we want to write all of our intervals as (a).



                Once you accept that (a) is the correct way of specifying intervals, indexing an array of length N as [0, N) is much nicer than [1, N+1).




                Two additional notes in favor of using (a) for intervals.



                The first point above is important because half-open intervals nicely decompose into other half-open intervals. This makes implementing divide-and-conquer algorithms like merge sort significantly less error prone.



                For example:



                • [4, 14) can be broken into the equal-sized intervals [4, 9) and [9, 14), and the middle index is computed as $9 = frac4 + 142$. This is quite clean and nice.

                • [4, 13], decomposes into [4, 8] and [9, 13], where you get the end of one sequence as $8 = frac4 + 13 + 12 - 1$, and the beginning of the next sequence as $9 = frac4 + 13 + 12$. It's easy to forget to add or subtract 1 somewhere.

                It's also a bit jarring to specify intervals with (b), because it feels unnatural to skip the first element when you're writing a loop.




                As for how to explain the above to your students, I think that they just need to accept that breaking sequences of integers in half is something they'll do later on, and then a few examples will quickly point to [,) intervals and zero indexing as the most natural choice.






                share|improve this answer
















                • 6




                  The half-intervals decomposing into half-intervals is a nice touch. Dijkstra's explanation does good job of justifying the use of the common scheme within CS as it was becoming a modern science.
                  – Gypsy Spellweaver
                  Sep 3 at 6:53






                • 20




                  Nice contribution and good insight. You've made this corner of the internet a better place :) Welcome to Computer Science Educators. Take a look around, I'd love to know what else you can add.
                  – Ben I.♦
                  Sep 3 at 12:11






                • 3




                  While a good reason to start indexing at 0, it feels much easier and more natural to mentally parse (d) and especially (c) than (a) or (b) - "numbers from x to y" in natural language usually means inclusive of both (or exclusive of both)
                  – msam
                  Sep 4 at 13:34






                • 2




                  @msam: Fully closed or fully open may be "more natural," but the subtraction property of half-open is extremely important. The interval [a, a+b) is exactly b elements long, without any pesky +1 or -1 terms. You simply cannot avoid having +1s and -1s everywhere when you use fully closed or fully open intervals.
                  – Kevin
                  Sep 5 at 1:30






                • 5




                  This also matches the behavior of the modulo operator, the return value of which lies in [0, n). number_of_values_ending_in_a_particular_digit[x % 10] += 1
                  – Roman Odaisky
                  Sep 5 at 1:48













                up vote
                184
                down vote










                up vote
                184
                down vote









                None of the reasons you suggest really get to the heart of why we use zero-indexing in CS. Dijkstra's EWD831 explains why this convention works out the best. It comes down to the fact that we want to represent sequences of integers as half-open intervals that are inclusive on the start side.




                To denote the subsequence of natural numbers 2, 3, ..., 12 without the pernicious three dots, four conventions are open to us

                a) 2 ≤ i < 13

                b) 1 < i ≤ 12

                c) 2 ≤ i ≤ 12

                d) 1 < i < 13




                To paraphrase Dijkstra:



                • (a) and (b) have the advantage that subtracting the bounds gives you the length, which is convenient because you don't need to remember to add or subtract 1.

                • (a) and (c) have the advantage that sequences starting with zero don't need a negative lower bound -- and negatives are no longer natural numbers.

                • (a) and (d) have the advantage that if you create an interval that starts with zero and shrink it down to zero-length, you don't need a negative for the upper bound.

                Because of the above, we want to write all of our intervals as (a).



                Once you accept that (a) is the correct way of specifying intervals, indexing an array of length N as [0, N) is much nicer than [1, N+1).




                Two additional notes in favor of using (a) for intervals.



                The first point above is important because half-open intervals nicely decompose into other half-open intervals. This makes implementing divide-and-conquer algorithms like merge sort significantly less error prone.



                For example:



                • [4, 14) can be broken into the equal-sized intervals [4, 9) and [9, 14), and the middle index is computed as $9 = frac4 + 142$. This is quite clean and nice.

                • [4, 13], decomposes into [4, 8] and [9, 13], where you get the end of one sequence as $8 = frac4 + 13 + 12 - 1$, and the beginning of the next sequence as $9 = frac4 + 13 + 12$. It's easy to forget to add or subtract 1 somewhere.

                It's also a bit jarring to specify intervals with (b), because it feels unnatural to skip the first element when you're writing a loop.




                As for how to explain the above to your students, I think that they just need to accept that breaking sequences of integers in half is something they'll do later on, and then a few examples will quickly point to [,) intervals and zero indexing as the most natural choice.






                share|improve this answer












                None of the reasons you suggest really get to the heart of why we use zero-indexing in CS. Dijkstra's EWD831 explains why this convention works out the best. It comes down to the fact that we want to represent sequences of integers as half-open intervals that are inclusive on the start side.




                To denote the subsequence of natural numbers 2, 3, ..., 12 without the pernicious three dots, four conventions are open to us

                a) 2 ≤ i < 13

                b) 1 < i ≤ 12

                c) 2 ≤ i ≤ 12

                d) 1 < i < 13




                To paraphrase Dijkstra:



                • (a) and (b) have the advantage that subtracting the bounds gives you the length, which is convenient because you don't need to remember to add or subtract 1.

                • (a) and (c) have the advantage that sequences starting with zero don't need a negative lower bound -- and negatives are no longer natural numbers.

                • (a) and (d) have the advantage that if you create an interval that starts with zero and shrink it down to zero-length, you don't need a negative for the upper bound.

                Because of the above, we want to write all of our intervals as (a).



                Once you accept that (a) is the correct way of specifying intervals, indexing an array of length N as [0, N) is much nicer than [1, N+1).




                Two additional notes in favor of using (a) for intervals.



                The first point above is important because half-open intervals nicely decompose into other half-open intervals. This makes implementing divide-and-conquer algorithms like merge sort significantly less error prone.



                For example:



                • [4, 14) can be broken into the equal-sized intervals [4, 9) and [9, 14), and the middle index is computed as $9 = frac4 + 142$. This is quite clean and nice.

                • [4, 13], decomposes into [4, 8] and [9, 13], where you get the end of one sequence as $8 = frac4 + 13 + 12 - 1$, and the beginning of the next sequence as $9 = frac4 + 13 + 12$. It's easy to forget to add or subtract 1 somewhere.

                It's also a bit jarring to specify intervals with (b), because it feels unnatural to skip the first element when you're writing a loop.




                As for how to explain the above to your students, I think that they just need to accept that breaking sequences of integers in half is something they'll do later on, and then a few examples will quickly point to [,) intervals and zero indexing as the most natural choice.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Sep 3 at 6:34









                drawoc

                1,339114




                1,339114







                • 6




                  The half-intervals decomposing into half-intervals is a nice touch. Dijkstra's explanation does good job of justifying the use of the common scheme within CS as it was becoming a modern science.
                  – Gypsy Spellweaver
                  Sep 3 at 6:53






                • 20




                  Nice contribution and good insight. You've made this corner of the internet a better place :) Welcome to Computer Science Educators. Take a look around, I'd love to know what else you can add.
                  – Ben I.♦
                  Sep 3 at 12:11






                • 3




                  While a good reason to start indexing at 0, it feels much easier and more natural to mentally parse (d) and especially (c) than (a) or (b) - "numbers from x to y" in natural language usually means inclusive of both (or exclusive of both)
                  – msam
                  Sep 4 at 13:34






                • 2




                  @msam: Fully closed or fully open may be "more natural," but the subtraction property of half-open is extremely important. The interval [a, a+b) is exactly b elements long, without any pesky +1 or -1 terms. You simply cannot avoid having +1s and -1s everywhere when you use fully closed or fully open intervals.
                  – Kevin
                  Sep 5 at 1:30






                • 5




                  This also matches the behavior of the modulo operator, the return value of which lies in [0, n). number_of_values_ending_in_a_particular_digit[x % 10] += 1
                  – Roman Odaisky
                  Sep 5 at 1:48













                • 6




                  The half-intervals decomposing into half-intervals is a nice touch. Dijkstra's explanation does good job of justifying the use of the common scheme within CS as it was becoming a modern science.
                  – Gypsy Spellweaver
                  Sep 3 at 6:53






                • 20




                  Nice contribution and good insight. You've made this corner of the internet a better place :) Welcome to Computer Science Educators. Take a look around, I'd love to know what else you can add.
                  – Ben I.♦
                  Sep 3 at 12:11






                • 3




                  While a good reason to start indexing at 0, it feels much easier and more natural to mentally parse (d) and especially (c) than (a) or (b) - "numbers from x to y" in natural language usually means inclusive of both (or exclusive of both)
                  – msam
                  Sep 4 at 13:34






                • 2




                  @msam: Fully closed or fully open may be "more natural," but the subtraction property of half-open is extremely important. The interval [a, a+b) is exactly b elements long, without any pesky +1 or -1 terms. You simply cannot avoid having +1s and -1s everywhere when you use fully closed or fully open intervals.
                  – Kevin
                  Sep 5 at 1:30






                • 5




                  This also matches the behavior of the modulo operator, the return value of which lies in [0, n). number_of_values_ending_in_a_particular_digit[x % 10] += 1
                  – Roman Odaisky
                  Sep 5 at 1:48








                6




                6




                The half-intervals decomposing into half-intervals is a nice touch. Dijkstra's explanation does good job of justifying the use of the common scheme within CS as it was becoming a modern science.
                – Gypsy Spellweaver
                Sep 3 at 6:53




                The half-intervals decomposing into half-intervals is a nice touch. Dijkstra's explanation does good job of justifying the use of the common scheme within CS as it was becoming a modern science.
                – Gypsy Spellweaver
                Sep 3 at 6:53




                20




                20




                Nice contribution and good insight. You've made this corner of the internet a better place :) Welcome to Computer Science Educators. Take a look around, I'd love to know what else you can add.
                – Ben I.♦
                Sep 3 at 12:11




                Nice contribution and good insight. You've made this corner of the internet a better place :) Welcome to Computer Science Educators. Take a look around, I'd love to know what else you can add.
                – Ben I.♦
                Sep 3 at 12:11




                3




                3




                While a good reason to start indexing at 0, it feels much easier and more natural to mentally parse (d) and especially (c) than (a) or (b) - "numbers from x to y" in natural language usually means inclusive of both (or exclusive of both)
                – msam
                Sep 4 at 13:34




                While a good reason to start indexing at 0, it feels much easier and more natural to mentally parse (d) and especially (c) than (a) or (b) - "numbers from x to y" in natural language usually means inclusive of both (or exclusive of both)
                – msam
                Sep 4 at 13:34




                2




                2




                @msam: Fully closed or fully open may be "more natural," but the subtraction property of half-open is extremely important. The interval [a, a+b) is exactly b elements long, without any pesky +1 or -1 terms. You simply cannot avoid having +1s and -1s everywhere when you use fully closed or fully open intervals.
                – Kevin
                Sep 5 at 1:30




                @msam: Fully closed or fully open may be "more natural," but the subtraction property of half-open is extremely important. The interval [a, a+b) is exactly b elements long, without any pesky +1 or -1 terms. You simply cannot avoid having +1s and -1s everywhere when you use fully closed or fully open intervals.
                – Kevin
                Sep 5 at 1:30




                5




                5




                This also matches the behavior of the modulo operator, the return value of which lies in [0, n). number_of_values_ending_in_a_particular_digit[x % 10] += 1
                – Roman Odaisky
                Sep 5 at 1:48





                This also matches the behavior of the modulo operator, the return value of which lies in [0, n). number_of_values_ending_in_a_particular_digit[x % 10] += 1
                – Roman Odaisky
                Sep 5 at 1:48











                up vote
                83
                down vote













                If I can modify the question, I can answer what I believe you are looking for.




                The question is "Why do we count starting from zero?" The answer is "we don't" Not even in computer science do we "count" from zero. A list with 15 items in it from outside CS still has 15 items in it inside CS realms. Many languages include a count type function for arrays, and such a function would still return 15 for that list.




                If the question becomes "Why do we index from zero?" then it has a different answer. This time the answer is "because that's the way everyone else does it." When we separate the concepts of "indexing" and "counting" things become simpler to explain. Often true of any concept, use the proper terminology and many difficulties are eliminated.




                As to why we, as humans, index from zero, while counting from one, only requires a little thought before clarity arrives. Assuming a classroom environment, where the class period lasts for a specified time, perhaps 50 minutes, you can ask at very near, but after, a 60 second mark, how many minutes the class has been in session. If asked at 5:02 minutes into class, the answer will be five minutes. Ask them how long class had been in session five minutes ago, which would be around 0:20 into the class period. The answer should be zero minutes. Once they accept that it was zero minutes, even at 0:59 into the class, you can emphasize that even though the class time had not reached a full minute, it is still class time, and should have some way of "indexing" it. Since the number before one is zero, it must have an index of zero. Hence the "first minute" (by counting) has an index of zero.



                The same thought experiments can be conducted with a ruler/tape measure, where the measure starts at zero, and the first centimeter/inch is called, and written, zero. The same concept applies to any distance, such as miles or kilometers, but those are harder to fit into the classroom. In the USA, most highways have "mile markers" that help in locating people for emergency responders. They mark the distance from the beginning of that highway on its south-western end. (The beginning is at the state line if it crosses from one state to another.) "Mile marker" 1 is set after the first mile is completed. "Mile marker" 0 is sometimes seen on the state line, though it is not always there. The first mile, in counting, has an index of 0.



                As another example, though not quite as helpful, and requiring that the students have a level of algebra experience to apprehend it, is exponents. Limiting it to non-negative powers of ten and applying it to whole numbers only, we can use the fact that $10^0 = 1$ while $10^1 = 10$. The exponent represents the index for how many places to the right to move (again distance to move) the decimal point, while the count of the digits before the decimal point will be 1 larger.



                Final demonstration: "What is the index of the first position on the volume knob below?" "What is the index of the last position on that volume knob?" "How many positions can you count on that volume knob?"



                Volume Knob




                Once the "index" vs "count" is solved, you can move into the CS realm, where the same practices are followed.



                An array is "indexed" from zero and "counted" from one. Why? Because that is the way humans index and count. It certainly comes in handy when doing arithmetic with memory addresses, and there's nothing wrong with taking advantage of things that "just work" naturally. Similar shortcuts include dividing and multiplying by powers of two by shifting bits to the right of left. Its usefulness to the compiler, or the developer, however, is not the why. Such "benefits" are only side effects of "what was" before CS was a reality.



                Bottom line is that index from zero and count from one existed a very long time before electronic computers were invented. Like any other science, computer science has to build upon what already exists before inventing new things. Zero-based indexing is one such "per-existing" thing.






                share|improve this answer


















                • 6




                  You claim we count from 1. But why don't your examples show that we count from 0? Once we have counted the class's first minute, class has been in session a minute -- counting it is not the start of the counting process but the completion of the subtask of counting that minute. This is independent of whether we index it as "0th" or "1st".
                  – Rosie F
                  Sep 3 at 7:58






                • 17




                  I think your answer is in essence just "everywhere we start counting at one, but start indexing at zero - but not a lot of the answer will help children grasping the idea of what an "index" is. - The following task might help "Please paint the first 5cm of this paper red, tell your partner where he should start painting and where he should stop." And he will naturally tell his partner "Paint everything from 0 to 5 red"
                  – Falco
                  Sep 3 at 11:52






                • 8




                  @Bergi No, all respect to Asimov, we shouldn't say "zeroth" mile. That's the difference between counting and indexing. It is the "first" mile, and has an index of "zero". The second mile has an index of one. Until counting and indexing are separated in the individual's mind, such problems will continue to rise.
                  – Gypsy Spellweaver
                  Sep 3 at 17:09






                • 6




                  @Barmar: Yes, there are many places where buildings have a floor 0, though it is typically called the "ground floor" and labelled "G" on elevator buttons. Unlike North America, where the ground floor is floor 1 and one storey up is floor 2, in Europe, the UK, and Australia the convention is that the ground floor is 0 and one storey up is floor 1.
                  – user128216
                  Sep 3 at 23:18







                • 17




                  Perhaps rather than rulers and road markers, you could ask the students to think about why it's best to say a new born baby is 0 not 1.
                  – curiousdannii
                  Sep 4 at 10:28














                up vote
                83
                down vote













                If I can modify the question, I can answer what I believe you are looking for.




                The question is "Why do we count starting from zero?" The answer is "we don't" Not even in computer science do we "count" from zero. A list with 15 items in it from outside CS still has 15 items in it inside CS realms. Many languages include a count type function for arrays, and such a function would still return 15 for that list.




                If the question becomes "Why do we index from zero?" then it has a different answer. This time the answer is "because that's the way everyone else does it." When we separate the concepts of "indexing" and "counting" things become simpler to explain. Often true of any concept, use the proper terminology and many difficulties are eliminated.




                As to why we, as humans, index from zero, while counting from one, only requires a little thought before clarity arrives. Assuming a classroom environment, where the class period lasts for a specified time, perhaps 50 minutes, you can ask at very near, but after, a 60 second mark, how many minutes the class has been in session. If asked at 5:02 minutes into class, the answer will be five minutes. Ask them how long class had been in session five minutes ago, which would be around 0:20 into the class period. The answer should be zero minutes. Once they accept that it was zero minutes, even at 0:59 into the class, you can emphasize that even though the class time had not reached a full minute, it is still class time, and should have some way of "indexing" it. Since the number before one is zero, it must have an index of zero. Hence the "first minute" (by counting) has an index of zero.



                The same thought experiments can be conducted with a ruler/tape measure, where the measure starts at zero, and the first centimeter/inch is called, and written, zero. The same concept applies to any distance, such as miles or kilometers, but those are harder to fit into the classroom. In the USA, most highways have "mile markers" that help in locating people for emergency responders. They mark the distance from the beginning of that highway on its south-western end. (The beginning is at the state line if it crosses from one state to another.) "Mile marker" 1 is set after the first mile is completed. "Mile marker" 0 is sometimes seen on the state line, though it is not always there. The first mile, in counting, has an index of 0.



                As another example, though not quite as helpful, and requiring that the students have a level of algebra experience to apprehend it, is exponents. Limiting it to non-negative powers of ten and applying it to whole numbers only, we can use the fact that $10^0 = 1$ while $10^1 = 10$. The exponent represents the index for how many places to the right to move (again distance to move) the decimal point, while the count of the digits before the decimal point will be 1 larger.



                Final demonstration: "What is the index of the first position on the volume knob below?" "What is the index of the last position on that volume knob?" "How many positions can you count on that volume knob?"



                Volume Knob




                Once the "index" vs "count" is solved, you can move into the CS realm, where the same practices are followed.



                An array is "indexed" from zero and "counted" from one. Why? Because that is the way humans index and count. It certainly comes in handy when doing arithmetic with memory addresses, and there's nothing wrong with taking advantage of things that "just work" naturally. Similar shortcuts include dividing and multiplying by powers of two by shifting bits to the right of left. Its usefulness to the compiler, or the developer, however, is not the why. Such "benefits" are only side effects of "what was" before CS was a reality.



                Bottom line is that index from zero and count from one existed a very long time before electronic computers were invented. Like any other science, computer science has to build upon what already exists before inventing new things. Zero-based indexing is one such "per-existing" thing.






                share|improve this answer


















                • 6




                  You claim we count from 1. But why don't your examples show that we count from 0? Once we have counted the class's first minute, class has been in session a minute -- counting it is not the start of the counting process but the completion of the subtask of counting that minute. This is independent of whether we index it as "0th" or "1st".
                  – Rosie F
                  Sep 3 at 7:58






                • 17




                  I think your answer is in essence just "everywhere we start counting at one, but start indexing at zero - but not a lot of the answer will help children grasping the idea of what an "index" is. - The following task might help "Please paint the first 5cm of this paper red, tell your partner where he should start painting and where he should stop." And he will naturally tell his partner "Paint everything from 0 to 5 red"
                  – Falco
                  Sep 3 at 11:52






                • 8




                  @Bergi No, all respect to Asimov, we shouldn't say "zeroth" mile. That's the difference between counting and indexing. It is the "first" mile, and has an index of "zero". The second mile has an index of one. Until counting and indexing are separated in the individual's mind, such problems will continue to rise.
                  – Gypsy Spellweaver
                  Sep 3 at 17:09






                • 6




                  @Barmar: Yes, there are many places where buildings have a floor 0, though it is typically called the "ground floor" and labelled "G" on elevator buttons. Unlike North America, where the ground floor is floor 1 and one storey up is floor 2, in Europe, the UK, and Australia the convention is that the ground floor is 0 and one storey up is floor 1.
                  – user128216
                  Sep 3 at 23:18







                • 17




                  Perhaps rather than rulers and road markers, you could ask the students to think about why it's best to say a new born baby is 0 not 1.
                  – curiousdannii
                  Sep 4 at 10:28












                up vote
                83
                down vote










                up vote
                83
                down vote









                If I can modify the question, I can answer what I believe you are looking for.




                The question is "Why do we count starting from zero?" The answer is "we don't" Not even in computer science do we "count" from zero. A list with 15 items in it from outside CS still has 15 items in it inside CS realms. Many languages include a count type function for arrays, and such a function would still return 15 for that list.




                If the question becomes "Why do we index from zero?" then it has a different answer. This time the answer is "because that's the way everyone else does it." When we separate the concepts of "indexing" and "counting" things become simpler to explain. Often true of any concept, use the proper terminology and many difficulties are eliminated.




                As to why we, as humans, index from zero, while counting from one, only requires a little thought before clarity arrives. Assuming a classroom environment, where the class period lasts for a specified time, perhaps 50 minutes, you can ask at very near, but after, a 60 second mark, how many minutes the class has been in session. If asked at 5:02 minutes into class, the answer will be five minutes. Ask them how long class had been in session five minutes ago, which would be around 0:20 into the class period. The answer should be zero minutes. Once they accept that it was zero minutes, even at 0:59 into the class, you can emphasize that even though the class time had not reached a full minute, it is still class time, and should have some way of "indexing" it. Since the number before one is zero, it must have an index of zero. Hence the "first minute" (by counting) has an index of zero.



                The same thought experiments can be conducted with a ruler/tape measure, where the measure starts at zero, and the first centimeter/inch is called, and written, zero. The same concept applies to any distance, such as miles or kilometers, but those are harder to fit into the classroom. In the USA, most highways have "mile markers" that help in locating people for emergency responders. They mark the distance from the beginning of that highway on its south-western end. (The beginning is at the state line if it crosses from one state to another.) "Mile marker" 1 is set after the first mile is completed. "Mile marker" 0 is sometimes seen on the state line, though it is not always there. The first mile, in counting, has an index of 0.



                As another example, though not quite as helpful, and requiring that the students have a level of algebra experience to apprehend it, is exponents. Limiting it to non-negative powers of ten and applying it to whole numbers only, we can use the fact that $10^0 = 1$ while $10^1 = 10$. The exponent represents the index for how many places to the right to move (again distance to move) the decimal point, while the count of the digits before the decimal point will be 1 larger.



                Final demonstration: "What is the index of the first position on the volume knob below?" "What is the index of the last position on that volume knob?" "How many positions can you count on that volume knob?"



                Volume Knob




                Once the "index" vs "count" is solved, you can move into the CS realm, where the same practices are followed.



                An array is "indexed" from zero and "counted" from one. Why? Because that is the way humans index and count. It certainly comes in handy when doing arithmetic with memory addresses, and there's nothing wrong with taking advantage of things that "just work" naturally. Similar shortcuts include dividing and multiplying by powers of two by shifting bits to the right of left. Its usefulness to the compiler, or the developer, however, is not the why. Such "benefits" are only side effects of "what was" before CS was a reality.



                Bottom line is that index from zero and count from one existed a very long time before electronic computers were invented. Like any other science, computer science has to build upon what already exists before inventing new things. Zero-based indexing is one such "per-existing" thing.






                share|improve this answer














                If I can modify the question, I can answer what I believe you are looking for.




                The question is "Why do we count starting from zero?" The answer is "we don't" Not even in computer science do we "count" from zero. A list with 15 items in it from outside CS still has 15 items in it inside CS realms. Many languages include a count type function for arrays, and such a function would still return 15 for that list.




                If the question becomes "Why do we index from zero?" then it has a different answer. This time the answer is "because that's the way everyone else does it." When we separate the concepts of "indexing" and "counting" things become simpler to explain. Often true of any concept, use the proper terminology and many difficulties are eliminated.




                As to why we, as humans, index from zero, while counting from one, only requires a little thought before clarity arrives. Assuming a classroom environment, where the class period lasts for a specified time, perhaps 50 minutes, you can ask at very near, but after, a 60 second mark, how many minutes the class has been in session. If asked at 5:02 minutes into class, the answer will be five minutes. Ask them how long class had been in session five minutes ago, which would be around 0:20 into the class period. The answer should be zero minutes. Once they accept that it was zero minutes, even at 0:59 into the class, you can emphasize that even though the class time had not reached a full minute, it is still class time, and should have some way of "indexing" it. Since the number before one is zero, it must have an index of zero. Hence the "first minute" (by counting) has an index of zero.



                The same thought experiments can be conducted with a ruler/tape measure, where the measure starts at zero, and the first centimeter/inch is called, and written, zero. The same concept applies to any distance, such as miles or kilometers, but those are harder to fit into the classroom. In the USA, most highways have "mile markers" that help in locating people for emergency responders. They mark the distance from the beginning of that highway on its south-western end. (The beginning is at the state line if it crosses from one state to another.) "Mile marker" 1 is set after the first mile is completed. "Mile marker" 0 is sometimes seen on the state line, though it is not always there. The first mile, in counting, has an index of 0.



                As another example, though not quite as helpful, and requiring that the students have a level of algebra experience to apprehend it, is exponents. Limiting it to non-negative powers of ten and applying it to whole numbers only, we can use the fact that $10^0 = 1$ while $10^1 = 10$. The exponent represents the index for how many places to the right to move (again distance to move) the decimal point, while the count of the digits before the decimal point will be 1 larger.



                Final demonstration: "What is the index of the first position on the volume knob below?" "What is the index of the last position on that volume knob?" "How many positions can you count on that volume knob?"



                Volume Knob




                Once the "index" vs "count" is solved, you can move into the CS realm, where the same practices are followed.



                An array is "indexed" from zero and "counted" from one. Why? Because that is the way humans index and count. It certainly comes in handy when doing arithmetic with memory addresses, and there's nothing wrong with taking advantage of things that "just work" naturally. Similar shortcuts include dividing and multiplying by powers of two by shifting bits to the right of left. Its usefulness to the compiler, or the developer, however, is not the why. Such "benefits" are only side effects of "what was" before CS was a reality.



                Bottom line is that index from zero and count from one existed a very long time before electronic computers were invented. Like any other science, computer science has to build upon what already exists before inventing new things. Zero-based indexing is one such "per-existing" thing.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 37 mins ago

























                answered Sep 3 at 4:00









                Gypsy Spellweaver

                3,92411032




                3,92411032







                • 6




                  You claim we count from 1. But why don't your examples show that we count from 0? Once we have counted the class's first minute, class has been in session a minute -- counting it is not the start of the counting process but the completion of the subtask of counting that minute. This is independent of whether we index it as "0th" or "1st".
                  – Rosie F
                  Sep 3 at 7:58






                • 17




                  I think your answer is in essence just "everywhere we start counting at one, but start indexing at zero - but not a lot of the answer will help children grasping the idea of what an "index" is. - The following task might help "Please paint the first 5cm of this paper red, tell your partner where he should start painting and where he should stop." And he will naturally tell his partner "Paint everything from 0 to 5 red"
                  – Falco
                  Sep 3 at 11:52






                • 8




                  @Bergi No, all respect to Asimov, we shouldn't say "zeroth" mile. That's the difference between counting and indexing. It is the "first" mile, and has an index of "zero". The second mile has an index of one. Until counting and indexing are separated in the individual's mind, such problems will continue to rise.
                  – Gypsy Spellweaver
                  Sep 3 at 17:09






                • 6




                  @Barmar: Yes, there are many places where buildings have a floor 0, though it is typically called the "ground floor" and labelled "G" on elevator buttons. Unlike North America, where the ground floor is floor 1 and one storey up is floor 2, in Europe, the UK, and Australia the convention is that the ground floor is 0 and one storey up is floor 1.
                  – user128216
                  Sep 3 at 23:18







                • 17




                  Perhaps rather than rulers and road markers, you could ask the students to think about why it's best to say a new born baby is 0 not 1.
                  – curiousdannii
                  Sep 4 at 10:28












                • 6




                  You claim we count from 1. But why don't your examples show that we count from 0? Once we have counted the class's first minute, class has been in session a minute -- counting it is not the start of the counting process but the completion of the subtask of counting that minute. This is independent of whether we index it as "0th" or "1st".
                  – Rosie F
                  Sep 3 at 7:58






                • 17




                  I think your answer is in essence just "everywhere we start counting at one, but start indexing at zero - but not a lot of the answer will help children grasping the idea of what an "index" is. - The following task might help "Please paint the first 5cm of this paper red, tell your partner where he should start painting and where he should stop." And he will naturally tell his partner "Paint everything from 0 to 5 red"
                  – Falco
                  Sep 3 at 11:52






                • 8




                  @Bergi No, all respect to Asimov, we shouldn't say "zeroth" mile. That's the difference between counting and indexing. It is the "first" mile, and has an index of "zero". The second mile has an index of one. Until counting and indexing are separated in the individual's mind, such problems will continue to rise.
                  – Gypsy Spellweaver
                  Sep 3 at 17:09






                • 6




                  @Barmar: Yes, there are many places where buildings have a floor 0, though it is typically called the "ground floor" and labelled "G" on elevator buttons. Unlike North America, where the ground floor is floor 1 and one storey up is floor 2, in Europe, the UK, and Australia the convention is that the ground floor is 0 and one storey up is floor 1.
                  – user128216
                  Sep 3 at 23:18







                • 17




                  Perhaps rather than rulers and road markers, you could ask the students to think about why it's best to say a new born baby is 0 not 1.
                  – curiousdannii
                  Sep 4 at 10:28







                6




                6




                You claim we count from 1. But why don't your examples show that we count from 0? Once we have counted the class's first minute, class has been in session a minute -- counting it is not the start of the counting process but the completion of the subtask of counting that minute. This is independent of whether we index it as "0th" or "1st".
                – Rosie F
                Sep 3 at 7:58




                You claim we count from 1. But why don't your examples show that we count from 0? Once we have counted the class's first minute, class has been in session a minute -- counting it is not the start of the counting process but the completion of the subtask of counting that minute. This is independent of whether we index it as "0th" or "1st".
                – Rosie F
                Sep 3 at 7:58




                17




                17




                I think your answer is in essence just "everywhere we start counting at one, but start indexing at zero - but not a lot of the answer will help children grasping the idea of what an "index" is. - The following task might help "Please paint the first 5cm of this paper red, tell your partner where he should start painting and where he should stop." And he will naturally tell his partner "Paint everything from 0 to 5 red"
                – Falco
                Sep 3 at 11:52




                I think your answer is in essence just "everywhere we start counting at one, but start indexing at zero - but not a lot of the answer will help children grasping the idea of what an "index" is. - The following task might help "Please paint the first 5cm of this paper red, tell your partner where he should start painting and where he should stop." And he will naturally tell his partner "Paint everything from 0 to 5 red"
                – Falco
                Sep 3 at 11:52




                8




                8




                @Bergi No, all respect to Asimov, we shouldn't say "zeroth" mile. That's the difference between counting and indexing. It is the "first" mile, and has an index of "zero". The second mile has an index of one. Until counting and indexing are separated in the individual's mind, such problems will continue to rise.
                – Gypsy Spellweaver
                Sep 3 at 17:09




                @Bergi No, all respect to Asimov, we shouldn't say "zeroth" mile. That's the difference between counting and indexing. It is the "first" mile, and has an index of "zero". The second mile has an index of one. Until counting and indexing are separated in the individual's mind, such problems will continue to rise.
                – Gypsy Spellweaver
                Sep 3 at 17:09




                6




                6




                @Barmar: Yes, there are many places where buildings have a floor 0, though it is typically called the "ground floor" and labelled "G" on elevator buttons. Unlike North America, where the ground floor is floor 1 and one storey up is floor 2, in Europe, the UK, and Australia the convention is that the ground floor is 0 and one storey up is floor 1.
                – user128216
                Sep 3 at 23:18





                @Barmar: Yes, there are many places where buildings have a floor 0, though it is typically called the "ground floor" and labelled "G" on elevator buttons. Unlike North America, where the ground floor is floor 1 and one storey up is floor 2, in Europe, the UK, and Australia the convention is that the ground floor is 0 and one storey up is floor 1.
                – user128216
                Sep 3 at 23:18





                17




                17




                Perhaps rather than rulers and road markers, you could ask the students to think about why it's best to say a new born baby is 0 not 1.
                – curiousdannii
                Sep 4 at 10:28




                Perhaps rather than rulers and road markers, you could ask the students to think about why it's best to say a new born baby is 0 not 1.
                – curiousdannii
                Sep 4 at 10:28










                up vote
                46
                down vote













                I'm surprised that the following hasn't been stated yet. All of the answers given so far seem to be "after the fact" explanations of something that is really based on the way people built most (not all) early computers as binary machines.



                To make things a bit more compact here, I'll assume we are creating a 4 bit (nibble) based machine. We don't want to use more binary components to build a nibble than we need to because we are cheap, so we use four bi-stable components (relays, vacuum tubes, transistors). We think of (perhaps) the two states as zero and one rather than, say, red and green.



                So we have (0000) through (1111) as the combinations of the four transistors of a nibble. We can interpret them any way that we like. Suppose we want to interpret them as integers. How shall we assign the different codes to integers. We could let (0000) represent 42, a fundamental universal constant, and (0001) represent 3, an approximation to pi and so on, but we realize pretty soon that any computations we want to do with such an encoding would be pretty complex - and complexity in a machine costs money. We are cheap, remember.



                So we notice that the codings are actually binary numbers. Well almost nobody used binary numbers before this so we start to think about it seriously now, as they have an application. I note that some early computers were actually decimal, not binary, but they recognized that while convenient it wasn't cheap.



                Now, using binary numbers, not just binary encoding, it becomes "obvious" that the codes represent zero through fifteen, not one through sixteen. Using (0000) to represent 1 just seems dumb at this level - and at this time.



                Now, (bit later) we want to index an "array" of nibbles. How shall we do it. Well we assign index numbers to the individual cells. Suppose we have four such cells. How shall we do it? We could use (0001) through (0100) to index them (1 through 4), but now (a-ha) if we have sixteen nibbles to index but start with one we can only get (our count) to fifteen without using another nibble or letting (0000) represent the last (sixteenth) cell. That seems dumb, so we (a-ha) index from zero. Now we can index sixteen cells with sixteen codes and it is cheap and pretty natural. The only cost is a bit of confusion in the minds of beginning programmers, but others will pay those costs and our machines can be cheap.



                No contest. Index from zero.



                The other answers here explore why the arithmetic inside the machine is cheap this way, so I won't repeat it here. But note that all of this happened before any languages at all were invented other than the simplest of machine coding without any abstraction facilities at all. It was just economics and engineering. Make it simple, keep it cheap.






                share|improve this answer


















                • 4




                  Give your students this simple task and they will find the answer themselves: Number these ten students, each with a unique number, but you can only use a single digit - they will quickly come up with the solution to number then 0 to 9 - and that is why we index starting at zero, we don't like waste :-)
                  – Falco
                  Sep 3 at 11:46






                • 12




                  Interestingly, all the early languages have one-based (or user-defined) indexing (e.g. Fortran (1957), Algol (1958)), or don't have a notion of "array" at all (Lisp (1957)). Zero-based indexing is a rather modern invention.
                  – Jörg W Mittag
                  Sep 3 at 14:51






                • 7




                  Interesting that on rotary telephones 0 (with ten pulses) comes after 9, but then pulsing the line zero times doesn't really work physically.
                  – Scott Rowe
                  Sep 3 at 17:36






                • 5




                  @JörgWMittag: Interesting! I wonder if designers of early languages were thinking that anyone who knew how computers and binary numbers really worked would just write in assembly language. Early computers were slow, and early compilers presumably didn't optimize well / at all. Anyway, this answer is exactly what occurred to me, too: letting an N-bit index address a full 2^N elements. Power-of-2 buffer/object sizes are a big deal.
                  – Peter Cordes
                  Sep 4 at 0:01






                • 5




                  @ScottRowe zero had 11 pulses, and one had 2 pulses. This was to stop the equipment reacting to random single pulses.
                  – ctrl-alt-delor
                  Sep 4 at 8:09














                up vote
                46
                down vote













                I'm surprised that the following hasn't been stated yet. All of the answers given so far seem to be "after the fact" explanations of something that is really based on the way people built most (not all) early computers as binary machines.



                To make things a bit more compact here, I'll assume we are creating a 4 bit (nibble) based machine. We don't want to use more binary components to build a nibble than we need to because we are cheap, so we use four bi-stable components (relays, vacuum tubes, transistors). We think of (perhaps) the two states as zero and one rather than, say, red and green.



                So we have (0000) through (1111) as the combinations of the four transistors of a nibble. We can interpret them any way that we like. Suppose we want to interpret them as integers. How shall we assign the different codes to integers. We could let (0000) represent 42, a fundamental universal constant, and (0001) represent 3, an approximation to pi and so on, but we realize pretty soon that any computations we want to do with such an encoding would be pretty complex - and complexity in a machine costs money. We are cheap, remember.



                So we notice that the codings are actually binary numbers. Well almost nobody used binary numbers before this so we start to think about it seriously now, as they have an application. I note that some early computers were actually decimal, not binary, but they recognized that while convenient it wasn't cheap.



                Now, using binary numbers, not just binary encoding, it becomes "obvious" that the codes represent zero through fifteen, not one through sixteen. Using (0000) to represent 1 just seems dumb at this level - and at this time.



                Now, (bit later) we want to index an "array" of nibbles. How shall we do it. Well we assign index numbers to the individual cells. Suppose we have four such cells. How shall we do it? We could use (0001) through (0100) to index them (1 through 4), but now (a-ha) if we have sixteen nibbles to index but start with one we can only get (our count) to fifteen without using another nibble or letting (0000) represent the last (sixteenth) cell. That seems dumb, so we (a-ha) index from zero. Now we can index sixteen cells with sixteen codes and it is cheap and pretty natural. The only cost is a bit of confusion in the minds of beginning programmers, but others will pay those costs and our machines can be cheap.



                No contest. Index from zero.



                The other answers here explore why the arithmetic inside the machine is cheap this way, so I won't repeat it here. But note that all of this happened before any languages at all were invented other than the simplest of machine coding without any abstraction facilities at all. It was just economics and engineering. Make it simple, keep it cheap.






                share|improve this answer


















                • 4




                  Give your students this simple task and they will find the answer themselves: Number these ten students, each with a unique number, but you can only use a single digit - they will quickly come up with the solution to number then 0 to 9 - and that is why we index starting at zero, we don't like waste :-)
                  – Falco
                  Sep 3 at 11:46






                • 12




                  Interestingly, all the early languages have one-based (or user-defined) indexing (e.g. Fortran (1957), Algol (1958)), or don't have a notion of "array" at all (Lisp (1957)). Zero-based indexing is a rather modern invention.
                  – Jörg W Mittag
                  Sep 3 at 14:51






                • 7




                  Interesting that on rotary telephones 0 (with ten pulses) comes after 9, but then pulsing the line zero times doesn't really work physically.
                  – Scott Rowe
                  Sep 3 at 17:36






                • 5




                  @JörgWMittag: Interesting! I wonder if designers of early languages were thinking that anyone who knew how computers and binary numbers really worked would just write in assembly language. Early computers were slow, and early compilers presumably didn't optimize well / at all. Anyway, this answer is exactly what occurred to me, too: letting an N-bit index address a full 2^N elements. Power-of-2 buffer/object sizes are a big deal.
                  – Peter Cordes
                  Sep 4 at 0:01






                • 5




                  @ScottRowe zero had 11 pulses, and one had 2 pulses. This was to stop the equipment reacting to random single pulses.
                  – ctrl-alt-delor
                  Sep 4 at 8:09












                up vote
                46
                down vote










                up vote
                46
                down vote









                I'm surprised that the following hasn't been stated yet. All of the answers given so far seem to be "after the fact" explanations of something that is really based on the way people built most (not all) early computers as binary machines.



                To make things a bit more compact here, I'll assume we are creating a 4 bit (nibble) based machine. We don't want to use more binary components to build a nibble than we need to because we are cheap, so we use four bi-stable components (relays, vacuum tubes, transistors). We think of (perhaps) the two states as zero and one rather than, say, red and green.



                So we have (0000) through (1111) as the combinations of the four transistors of a nibble. We can interpret them any way that we like. Suppose we want to interpret them as integers. How shall we assign the different codes to integers. We could let (0000) represent 42, a fundamental universal constant, and (0001) represent 3, an approximation to pi and so on, but we realize pretty soon that any computations we want to do with such an encoding would be pretty complex - and complexity in a machine costs money. We are cheap, remember.



                So we notice that the codings are actually binary numbers. Well almost nobody used binary numbers before this so we start to think about it seriously now, as they have an application. I note that some early computers were actually decimal, not binary, but they recognized that while convenient it wasn't cheap.



                Now, using binary numbers, not just binary encoding, it becomes "obvious" that the codes represent zero through fifteen, not one through sixteen. Using (0000) to represent 1 just seems dumb at this level - and at this time.



                Now, (bit later) we want to index an "array" of nibbles. How shall we do it. Well we assign index numbers to the individual cells. Suppose we have four such cells. How shall we do it? We could use (0001) through (0100) to index them (1 through 4), but now (a-ha) if we have sixteen nibbles to index but start with one we can only get (our count) to fifteen without using another nibble or letting (0000) represent the last (sixteenth) cell. That seems dumb, so we (a-ha) index from zero. Now we can index sixteen cells with sixteen codes and it is cheap and pretty natural. The only cost is a bit of confusion in the minds of beginning programmers, but others will pay those costs and our machines can be cheap.



                No contest. Index from zero.



                The other answers here explore why the arithmetic inside the machine is cheap this way, so I won't repeat it here. But note that all of this happened before any languages at all were invented other than the simplest of machine coding without any abstraction facilities at all. It was just economics and engineering. Make it simple, keep it cheap.






                share|improve this answer














                I'm surprised that the following hasn't been stated yet. All of the answers given so far seem to be "after the fact" explanations of something that is really based on the way people built most (not all) early computers as binary machines.



                To make things a bit more compact here, I'll assume we are creating a 4 bit (nibble) based machine. We don't want to use more binary components to build a nibble than we need to because we are cheap, so we use four bi-stable components (relays, vacuum tubes, transistors). We think of (perhaps) the two states as zero and one rather than, say, red and green.



                So we have (0000) through (1111) as the combinations of the four transistors of a nibble. We can interpret them any way that we like. Suppose we want to interpret them as integers. How shall we assign the different codes to integers. We could let (0000) represent 42, a fundamental universal constant, and (0001) represent 3, an approximation to pi and so on, but we realize pretty soon that any computations we want to do with such an encoding would be pretty complex - and complexity in a machine costs money. We are cheap, remember.



                So we notice that the codings are actually binary numbers. Well almost nobody used binary numbers before this so we start to think about it seriously now, as they have an application. I note that some early computers were actually decimal, not binary, but they recognized that while convenient it wasn't cheap.



                Now, using binary numbers, not just binary encoding, it becomes "obvious" that the codes represent zero through fifteen, not one through sixteen. Using (0000) to represent 1 just seems dumb at this level - and at this time.



                Now, (bit later) we want to index an "array" of nibbles. How shall we do it. Well we assign index numbers to the individual cells. Suppose we have four such cells. How shall we do it? We could use (0001) through (0100) to index them (1 through 4), but now (a-ha) if we have sixteen nibbles to index but start with one we can only get (our count) to fifteen without using another nibble or letting (0000) represent the last (sixteenth) cell. That seems dumb, so we (a-ha) index from zero. Now we can index sixteen cells with sixteen codes and it is cheap and pretty natural. The only cost is a bit of confusion in the minds of beginning programmers, but others will pay those costs and our machines can be cheap.



                No contest. Index from zero.



                The other answers here explore why the arithmetic inside the machine is cheap this way, so I won't repeat it here. But note that all of this happened before any languages at all were invented other than the simplest of machine coding without any abstraction facilities at all. It was just economics and engineering. Make it simple, keep it cheap.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Sep 3 at 11:45

























                answered Sep 3 at 11:05









                Buffy

                19.4k83778




                19.4k83778







                • 4




                  Give your students this simple task and they will find the answer themselves: Number these ten students, each with a unique number, but you can only use a single digit - they will quickly come up with the solution to number then 0 to 9 - and that is why we index starting at zero, we don't like waste :-)
                  – Falco
                  Sep 3 at 11:46






                • 12




                  Interestingly, all the early languages have one-based (or user-defined) indexing (e.g. Fortran (1957), Algol (1958)), or don't have a notion of "array" at all (Lisp (1957)). Zero-based indexing is a rather modern invention.
                  – Jörg W Mittag
                  Sep 3 at 14:51






                • 7




                  Interesting that on rotary telephones 0 (with ten pulses) comes after 9, but then pulsing the line zero times doesn't really work physically.
                  – Scott Rowe
                  Sep 3 at 17:36






                • 5




                  @JörgWMittag: Interesting! I wonder if designers of early languages were thinking that anyone who knew how computers and binary numbers really worked would just write in assembly language. Early computers were slow, and early compilers presumably didn't optimize well / at all. Anyway, this answer is exactly what occurred to me, too: letting an N-bit index address a full 2^N elements. Power-of-2 buffer/object sizes are a big deal.
                  – Peter Cordes
                  Sep 4 at 0:01






                • 5




                  @ScottRowe zero had 11 pulses, and one had 2 pulses. This was to stop the equipment reacting to random single pulses.
                  – ctrl-alt-delor
                  Sep 4 at 8:09












                • 4




                  Give your students this simple task and they will find the answer themselves: Number these ten students, each with a unique number, but you can only use a single digit - they will quickly come up with the solution to number then 0 to 9 - and that is why we index starting at zero, we don't like waste :-)
                  – Falco
                  Sep 3 at 11:46






                • 12




                  Interestingly, all the early languages have one-based (or user-defined) indexing (e.g. Fortran (1957), Algol (1958)), or don't have a notion of "array" at all (Lisp (1957)). Zero-based indexing is a rather modern invention.
                  – Jörg W Mittag
                  Sep 3 at 14:51






                • 7




                  Interesting that on rotary telephones 0 (with ten pulses) comes after 9, but then pulsing the line zero times doesn't really work physically.
                  – Scott Rowe
                  Sep 3 at 17:36






                • 5




                  @JörgWMittag: Interesting! I wonder if designers of early languages were thinking that anyone who knew how computers and binary numbers really worked would just write in assembly language. Early computers were slow, and early compilers presumably didn't optimize well / at all. Anyway, this answer is exactly what occurred to me, too: letting an N-bit index address a full 2^N elements. Power-of-2 buffer/object sizes are a big deal.
                  – Peter Cordes
                  Sep 4 at 0:01






                • 5




                  @ScottRowe zero had 11 pulses, and one had 2 pulses. This was to stop the equipment reacting to random single pulses.
                  – ctrl-alt-delor
                  Sep 4 at 8:09







                4




                4




                Give your students this simple task and they will find the answer themselves: Number these ten students, each with a unique number, but you can only use a single digit - they will quickly come up with the solution to number then 0 to 9 - and that is why we index starting at zero, we don't like waste :-)
                – Falco
                Sep 3 at 11:46




                Give your students this simple task and they will find the answer themselves: Number these ten students, each with a unique number, but you can only use a single digit - they will quickly come up with the solution to number then 0 to 9 - and that is why we index starting at zero, we don't like waste :-)
                – Falco
                Sep 3 at 11:46




                12




                12




                Interestingly, all the early languages have one-based (or user-defined) indexing (e.g. Fortran (1957), Algol (1958)), or don't have a notion of "array" at all (Lisp (1957)). Zero-based indexing is a rather modern invention.
                – Jörg W Mittag
                Sep 3 at 14:51




                Interestingly, all the early languages have one-based (or user-defined) indexing (e.g. Fortran (1957), Algol (1958)), or don't have a notion of "array" at all (Lisp (1957)). Zero-based indexing is a rather modern invention.
                – Jörg W Mittag
                Sep 3 at 14:51




                7




                7




                Interesting that on rotary telephones 0 (with ten pulses) comes after 9, but then pulsing the line zero times doesn't really work physically.
                – Scott Rowe
                Sep 3 at 17:36




                Interesting that on rotary telephones 0 (with ten pulses) comes after 9, but then pulsing the line zero times doesn't really work physically.
                – Scott Rowe
                Sep 3 at 17:36




                5




                5




                @JörgWMittag: Interesting! I wonder if designers of early languages were thinking that anyone who knew how computers and binary numbers really worked would just write in assembly language. Early computers were slow, and early compilers presumably didn't optimize well / at all. Anyway, this answer is exactly what occurred to me, too: letting an N-bit index address a full 2^N elements. Power-of-2 buffer/object sizes are a big deal.
                – Peter Cordes
                Sep 4 at 0:01




                @JörgWMittag: Interesting! I wonder if designers of early languages were thinking that anyone who knew how computers and binary numbers really worked would just write in assembly language. Early computers were slow, and early compilers presumably didn't optimize well / at all. Anyway, this answer is exactly what occurred to me, too: letting an N-bit index address a full 2^N elements. Power-of-2 buffer/object sizes are a big deal.
                – Peter Cordes
                Sep 4 at 0:01




                5




                5




                @ScottRowe zero had 11 pulses, and one had 2 pulses. This was to stop the equipment reacting to random single pulses.
                – ctrl-alt-delor
                Sep 4 at 8:09




                @ScottRowe zero had 11 pulses, and one had 2 pulses. This was to stop the equipment reacting to random single pulses.
                – ctrl-alt-delor
                Sep 4 at 8:09










                up vote
                32
                down vote













                You have already gotten several good answers about why zero-based indexing is useful, and you have been explained the difference between indexing and counting.



                I now want to challenge the basic premise of your question: it is not, in fact, universally agreed-upon that indexing starts at zero.



                In Excel, which is arguably the most widely-used programming language in the world (even though it doesn't look much like a "traditional" programming language), row-indexing starts at 1 and not 0, and column-indexing starts at A and not ε.



                In Visual Basic, the programmer can choose between zero-based and one-based indexing as the default indexing on a per-module (per-file) basis with the Option Base declaration. Plus, the programmer can declare the exact index range for each individual array using the To keyword in the array declaration, e.g.:



                Dim Count(100 to 500) as Integer


                This declares an array of integers named Count with indices ranging from 100 to 500 (inclusive).



                In the "Wirthian languages", i.e. Pascal and all its successors (Modula-2, Oberon, Component Pascal), arrays can be indexed by any arbitrary range of scalars (except reals).



                type
                foo = array[-10 .. 10] of real;
                (* an array of reals with indices ranging from -10 to +10 *)

                bar = array['b' .. 'g'] of 100..200;
                (* an array of integers from 100 to 200 with indices ranging from 'b' to 'g' *)

                weekday = (monday, tuesday, wednesday, thursday, friday, saturday, sunday);
                baz = array[tuesday..friday] of boolean;
                (* an array of booleans with indices ranging from tuesday to friday *)


                The Wirthian languages, in turn, inherited this from ALGOL-60 and ALGOL-68.



                Ada is similar, any discrete type can be used as the index type. Interestingly, idiomatic Ada style suggests using a range starting from 1 and not 0 when using an integer range as indices.



                In Eiffel, which is heavily inspired by Wirthian languages, array indices have explicit lower and upper bounds which can be any signed 32-bit integer, so you could have an array with indices ranging from -1000000 to -1, for example.



                In Fortran, the default is to start at 1, but like ALGOL, Pascal, Eiffel, and VB, you can specify any arbitrary lower and upper bound.



                In Matlab, indexing starts at 1. In APL and Perl, you can choose.



                Even in the "real world", there are different schemes. E.g., in Germany, the ground floor, i.e. the floor you enter from street level is called "ground floor", and is usually labelled 0 on elevator buttons that use numbers ("EG" if using letters). The floors above ground level are called "1st upper floor" (and so on) and labelled 1, 2, etc. (or "OG 1", …) The floors below ground level are called "1st lower floor" (and so on) and numbered -1, -2, etc. (or "UG 1", …)



                In the US, "1st floor" is the floor at ground level.



                Apparently, in Barcelona, there is a "ground floor", a "primary floor", and then the "first floor" is two stairs up from ground level.



                There is an interesting discussion about this on the Wiki: http://wiki.c2.com/?ZeroAndOneBasedIndexes



                I also found an essay that compares the syntactic and semantic noise of typical tasks using many different indexing schemes: http://enchantia.com/graphapp/doc/tech/arrays1.html






                share|improve this answer
















                • 1




                  It would seem that in Barcelona the "first floor" is one floor above the "primary floor", which name suggest that it is the "origin" for the building's life. The "ground floor" is presumably where garage, storage, utilities, and other facilities exist while regular rooms (kitchen etc.) are on the primary floor. Servants' quarters, are also likely to be "below" the primary floor. The ground floor would, presumably, have an index of -1.
                  – Gypsy Spellweaver
                  Sep 3 at 17:41






                • 2




                  In one university I have visited, the floor numbers were in feet above sea level. So not even consecutive. (This is also discussed here cseducators.stackexchange.com/a/215/204 )
                  – ctrl-alt-delor
                  Sep 4 at 8:19






                • 4




                  The reason for the numbering of floors in Barcelona is due to an old building regulation which dictated no buildings could have more than six floors. To work around this restriction, extra floor names were added so that the maximum numbered floor was always #6. The extra floor names are "Entresuelo" and "Principal" just above the ground floor, and "Atico" and "Sobreatico" just above the sixth floor. (Not all buildings will have all of these floor names).
                  – Aaron F
                  Sep 4 at 12:20






                • 2




                  Nothing Wirthian is inherited from ALGOL-68.
                  – philipxy
                  Sep 6 at 2:35






                • 2




                  +1, but this is only half the answer. The other half is that in the 70's C made the choice to directly support only indexing arrays from 0, as this made the compiler simplest (which was really C's primary design goal). Because C compilers were so simple, they were easy to make and put on any machine, and as a result of this and a few other bits of historical luck, C became super popular. As a result of that, a whole host of other languages took their lead from C.
                  – T.E.D.
                  Sep 6 at 14:32














                up vote
                32
                down vote













                You have already gotten several good answers about why zero-based indexing is useful, and you have been explained the difference between indexing and counting.



                I now want to challenge the basic premise of your question: it is not, in fact, universally agreed-upon that indexing starts at zero.



                In Excel, which is arguably the most widely-used programming language in the world (even though it doesn't look much like a "traditional" programming language), row-indexing starts at 1 and not 0, and column-indexing starts at A and not ε.



                In Visual Basic, the programmer can choose between zero-based and one-based indexing as the default indexing on a per-module (per-file) basis with the Option Base declaration. Plus, the programmer can declare the exact index range for each individual array using the To keyword in the array declaration, e.g.:



                Dim Count(100 to 500) as Integer


                This declares an array of integers named Count with indices ranging from 100 to 500 (inclusive).



                In the "Wirthian languages", i.e. Pascal and all its successors (Modula-2, Oberon, Component Pascal), arrays can be indexed by any arbitrary range of scalars (except reals).



                type
                foo = array[-10 .. 10] of real;
                (* an array of reals with indices ranging from -10 to +10 *)

                bar = array['b' .. 'g'] of 100..200;
                (* an array of integers from 100 to 200 with indices ranging from 'b' to 'g' *)

                weekday = (monday, tuesday, wednesday, thursday, friday, saturday, sunday);
                baz = array[tuesday..friday] of boolean;
                (* an array of booleans with indices ranging from tuesday to friday *)


                The Wirthian languages, in turn, inherited this from ALGOL-60 and ALGOL-68.



                Ada is similar, any discrete type can be used as the index type. Interestingly, idiomatic Ada style suggests using a range starting from 1 and not 0 when using an integer range as indices.



                In Eiffel, which is heavily inspired by Wirthian languages, array indices have explicit lower and upper bounds which can be any signed 32-bit integer, so you could have an array with indices ranging from -1000000 to -1, for example.



                In Fortran, the default is to start at 1, but like ALGOL, Pascal, Eiffel, and VB, you can specify any arbitrary lower and upper bound.



                In Matlab, indexing starts at 1. In APL and Perl, you can choose.



                Even in the "real world", there are different schemes. E.g., in Germany, the ground floor, i.e. the floor you enter from street level is called "ground floor", and is usually labelled 0 on elevator buttons that use numbers ("EG" if using letters). The floors above ground level are called "1st upper floor" (and so on) and labelled 1, 2, etc. (or "OG 1", …) The floors below ground level are called "1st lower floor" (and so on) and numbered -1, -2, etc. (or "UG 1", …)



                In the US, "1st floor" is the floor at ground level.



                Apparently, in Barcelona, there is a "ground floor", a "primary floor", and then the "first floor" is two stairs up from ground level.



                There is an interesting discussion about this on the Wiki: http://wiki.c2.com/?ZeroAndOneBasedIndexes



                I also found an essay that compares the syntactic and semantic noise of typical tasks using many different indexing schemes: http://enchantia.com/graphapp/doc/tech/arrays1.html






                share|improve this answer
















                • 1




                  It would seem that in Barcelona the "first floor" is one floor above the "primary floor", which name suggest that it is the "origin" for the building's life. The "ground floor" is presumably where garage, storage, utilities, and other facilities exist while regular rooms (kitchen etc.) are on the primary floor. Servants' quarters, are also likely to be "below" the primary floor. The ground floor would, presumably, have an index of -1.
                  – Gypsy Spellweaver
                  Sep 3 at 17:41






                • 2




                  In one university I have visited, the floor numbers were in feet above sea level. So not even consecutive. (This is also discussed here cseducators.stackexchange.com/a/215/204 )
                  – ctrl-alt-delor
                  Sep 4 at 8:19






                • 4




                  The reason for the numbering of floors in Barcelona is due to an old building regulation which dictated no buildings could have more than six floors. To work around this restriction, extra floor names were added so that the maximum numbered floor was always #6. The extra floor names are "Entresuelo" and "Principal" just above the ground floor, and "Atico" and "Sobreatico" just above the sixth floor. (Not all buildings will have all of these floor names).
                  – Aaron F
                  Sep 4 at 12:20






                • 2




                  Nothing Wirthian is inherited from ALGOL-68.
                  – philipxy
                  Sep 6 at 2:35






                • 2




                  +1, but this is only half the answer. The other half is that in the 70's C made the choice to directly support only indexing arrays from 0, as this made the compiler simplest (which was really C's primary design goal). Because C compilers were so simple, they were easy to make and put on any machine, and as a result of this and a few other bits of historical luck, C became super popular. As a result of that, a whole host of other languages took their lead from C.
                  – T.E.D.
                  Sep 6 at 14:32












                up vote
                32
                down vote










                up vote
                32
                down vote









                You have already gotten several good answers about why zero-based indexing is useful, and you have been explained the difference between indexing and counting.



                I now want to challenge the basic premise of your question: it is not, in fact, universally agreed-upon that indexing starts at zero.



                In Excel, which is arguably the most widely-used programming language in the world (even though it doesn't look much like a "traditional" programming language), row-indexing starts at 1 and not 0, and column-indexing starts at A and not ε.



                In Visual Basic, the programmer can choose between zero-based and one-based indexing as the default indexing on a per-module (per-file) basis with the Option Base declaration. Plus, the programmer can declare the exact index range for each individual array using the To keyword in the array declaration, e.g.:



                Dim Count(100 to 500) as Integer


                This declares an array of integers named Count with indices ranging from 100 to 500 (inclusive).



                In the "Wirthian languages", i.e. Pascal and all its successors (Modula-2, Oberon, Component Pascal), arrays can be indexed by any arbitrary range of scalars (except reals).



                type
                foo = array[-10 .. 10] of real;
                (* an array of reals with indices ranging from -10 to +10 *)

                bar = array['b' .. 'g'] of 100..200;
                (* an array of integers from 100 to 200 with indices ranging from 'b' to 'g' *)

                weekday = (monday, tuesday, wednesday, thursday, friday, saturday, sunday);
                baz = array[tuesday..friday] of boolean;
                (* an array of booleans with indices ranging from tuesday to friday *)


                The Wirthian languages, in turn, inherited this from ALGOL-60 and ALGOL-68.



                Ada is similar, any discrete type can be used as the index type. Interestingly, idiomatic Ada style suggests using a range starting from 1 and not 0 when using an integer range as indices.



                In Eiffel, which is heavily inspired by Wirthian languages, array indices have explicit lower and upper bounds which can be any signed 32-bit integer, so you could have an array with indices ranging from -1000000 to -1, for example.



                In Fortran, the default is to start at 1, but like ALGOL, Pascal, Eiffel, and VB, you can specify any arbitrary lower and upper bound.



                In Matlab, indexing starts at 1. In APL and Perl, you can choose.



                Even in the "real world", there are different schemes. E.g., in Germany, the ground floor, i.e. the floor you enter from street level is called "ground floor", and is usually labelled 0 on elevator buttons that use numbers ("EG" if using letters). The floors above ground level are called "1st upper floor" (and so on) and labelled 1, 2, etc. (or "OG 1", …) The floors below ground level are called "1st lower floor" (and so on) and numbered -1, -2, etc. (or "UG 1", …)



                In the US, "1st floor" is the floor at ground level.



                Apparently, in Barcelona, there is a "ground floor", a "primary floor", and then the "first floor" is two stairs up from ground level.



                There is an interesting discussion about this on the Wiki: http://wiki.c2.com/?ZeroAndOneBasedIndexes



                I also found an essay that compares the syntactic and semantic noise of typical tasks using many different indexing schemes: http://enchantia.com/graphapp/doc/tech/arrays1.html






                share|improve this answer












                You have already gotten several good answers about why zero-based indexing is useful, and you have been explained the difference between indexing and counting.



                I now want to challenge the basic premise of your question: it is not, in fact, universally agreed-upon that indexing starts at zero.



                In Excel, which is arguably the most widely-used programming language in the world (even though it doesn't look much like a "traditional" programming language), row-indexing starts at 1 and not 0, and column-indexing starts at A and not ε.



                In Visual Basic, the programmer can choose between zero-based and one-based indexing as the default indexing on a per-module (per-file) basis with the Option Base declaration. Plus, the programmer can declare the exact index range for each individual array using the To keyword in the array declaration, e.g.:



                Dim Count(100 to 500) as Integer


                This declares an array of integers named Count with indices ranging from 100 to 500 (inclusive).



                In the "Wirthian languages", i.e. Pascal and all its successors (Modula-2, Oberon, Component Pascal), arrays can be indexed by any arbitrary range of scalars (except reals).



                type
                foo = array[-10 .. 10] of real;
                (* an array of reals with indices ranging from -10 to +10 *)

                bar = array['b' .. 'g'] of 100..200;
                (* an array of integers from 100 to 200 with indices ranging from 'b' to 'g' *)

                weekday = (monday, tuesday, wednesday, thursday, friday, saturday, sunday);
                baz = array[tuesday..friday] of boolean;
                (* an array of booleans with indices ranging from tuesday to friday *)


                The Wirthian languages, in turn, inherited this from ALGOL-60 and ALGOL-68.



                Ada is similar, any discrete type can be used as the index type. Interestingly, idiomatic Ada style suggests using a range starting from 1 and not 0 when using an integer range as indices.



                In Eiffel, which is heavily inspired by Wirthian languages, array indices have explicit lower and upper bounds which can be any signed 32-bit integer, so you could have an array with indices ranging from -1000000 to -1, for example.



                In Fortran, the default is to start at 1, but like ALGOL, Pascal, Eiffel, and VB, you can specify any arbitrary lower and upper bound.



                In Matlab, indexing starts at 1. In APL and Perl, you can choose.



                Even in the "real world", there are different schemes. E.g., in Germany, the ground floor, i.e. the floor you enter from street level is called "ground floor", and is usually labelled 0 on elevator buttons that use numbers ("EG" if using letters). The floors above ground level are called "1st upper floor" (and so on) and labelled 1, 2, etc. (or "OG 1", …) The floors below ground level are called "1st lower floor" (and so on) and numbered -1, -2, etc. (or "UG 1", …)



                In the US, "1st floor" is the floor at ground level.



                Apparently, in Barcelona, there is a "ground floor", a "primary floor", and then the "first floor" is two stairs up from ground level.



                There is an interesting discussion about this on the Wiki: http://wiki.c2.com/?ZeroAndOneBasedIndexes



                I also found an essay that compares the syntactic and semantic noise of typical tasks using many different indexing schemes: http://enchantia.com/graphapp/doc/tech/arrays1.html







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Sep 3 at 9:38









                Jörg W Mittag

                66126




                66126







                • 1




                  It would seem that in Barcelona the "first floor" is one floor above the "primary floor", which name suggest that it is the "origin" for the building's life. The "ground floor" is presumably where garage, storage, utilities, and other facilities exist while regular rooms (kitchen etc.) are on the primary floor. Servants' quarters, are also likely to be "below" the primary floor. The ground floor would, presumably, have an index of -1.
                  – Gypsy Spellweaver
                  Sep 3 at 17:41






                • 2




                  In one university I have visited, the floor numbers were in feet above sea level. So not even consecutive. (This is also discussed here cseducators.stackexchange.com/a/215/204 )
                  – ctrl-alt-delor
                  Sep 4 at 8:19






                • 4




                  The reason for the numbering of floors in Barcelona is due to an old building regulation which dictated no buildings could have more than six floors. To work around this restriction, extra floor names were added so that the maximum numbered floor was always #6. The extra floor names are "Entresuelo" and "Principal" just above the ground floor, and "Atico" and "Sobreatico" just above the sixth floor. (Not all buildings will have all of these floor names).
                  – Aaron F
                  Sep 4 at 12:20






                • 2




                  Nothing Wirthian is inherited from ALGOL-68.
                  – philipxy
                  Sep 6 at 2:35






                • 2




                  +1, but this is only half the answer. The other half is that in the 70's C made the choice to directly support only indexing arrays from 0, as this made the compiler simplest (which was really C's primary design goal). Because C compilers were so simple, they were easy to make and put on any machine, and as a result of this and a few other bits of historical luck, C became super popular. As a result of that, a whole host of other languages took their lead from C.
                  – T.E.D.
                  Sep 6 at 14:32












                • 1




                  It would seem that in Barcelona the "first floor" is one floor above the "primary floor", which name suggest that it is the "origin" for the building's life. The "ground floor" is presumably where garage, storage, utilities, and other facilities exist while regular rooms (kitchen etc.) are on the primary floor. Servants' quarters, are also likely to be "below" the primary floor. The ground floor would, presumably, have an index of -1.
                  – Gypsy Spellweaver
                  Sep 3 at 17:41






                • 2




                  In one university I have visited, the floor numbers were in feet above sea level. So not even consecutive. (This is also discussed here cseducators.stackexchange.com/a/215/204 )
                  – ctrl-alt-delor
                  Sep 4 at 8:19






                • 4




                  The reason for the numbering of floors in Barcelona is due to an old building regulation which dictated no buildings could have more than six floors. To work around this restriction, extra floor names were added so that the maximum numbered floor was always #6. The extra floor names are "Entresuelo" and "Principal" just above the ground floor, and "Atico" and "Sobreatico" just above the sixth floor. (Not all buildings will have all of these floor names).
                  – Aaron F
                  Sep 4 at 12:20






                • 2




                  Nothing Wirthian is inherited from ALGOL-68.
                  – philipxy
                  Sep 6 at 2:35






                • 2




                  +1, but this is only half the answer. The other half is that in the 70's C made the choice to directly support only indexing arrays from 0, as this made the compiler simplest (which was really C's primary design goal). Because C compilers were so simple, they were easy to make and put on any machine, and as a result of this and a few other bits of historical luck, C became super popular. As a result of that, a whole host of other languages took their lead from C.
                  – T.E.D.
                  Sep 6 at 14:32







                1




                1




                It would seem that in Barcelona the "first floor" is one floor above the "primary floor", which name suggest that it is the "origin" for the building's life. The "ground floor" is presumably where garage, storage, utilities, and other facilities exist while regular rooms (kitchen etc.) are on the primary floor. Servants' quarters, are also likely to be "below" the primary floor. The ground floor would, presumably, have an index of -1.
                – Gypsy Spellweaver
                Sep 3 at 17:41




                It would seem that in Barcelona the "first floor" is one floor above the "primary floor", which name suggest that it is the "origin" for the building's life. The "ground floor" is presumably where garage, storage, utilities, and other facilities exist while regular rooms (kitchen etc.) are on the primary floor. Servants' quarters, are also likely to be "below" the primary floor. The ground floor would, presumably, have an index of -1.
                – Gypsy Spellweaver
                Sep 3 at 17:41




                2




                2




                In one university I have visited, the floor numbers were in feet above sea level. So not even consecutive. (This is also discussed here cseducators.stackexchange.com/a/215/204 )
                – ctrl-alt-delor
                Sep 4 at 8:19




                In one university I have visited, the floor numbers were in feet above sea level. So not even consecutive. (This is also discussed here cseducators.stackexchange.com/a/215/204 )
                – ctrl-alt-delor
                Sep 4 at 8:19




                4




                4




                The reason for the numbering of floors in Barcelona is due to an old building regulation which dictated no buildings could have more than six floors. To work around this restriction, extra floor names were added so that the maximum numbered floor was always #6. The extra floor names are "Entresuelo" and "Principal" just above the ground floor, and "Atico" and "Sobreatico" just above the sixth floor. (Not all buildings will have all of these floor names).
                – Aaron F
                Sep 4 at 12:20




                The reason for the numbering of floors in Barcelona is due to an old building regulation which dictated no buildings could have more than six floors. To work around this restriction, extra floor names were added so that the maximum numbered floor was always #6. The extra floor names are "Entresuelo" and "Principal" just above the ground floor, and "Atico" and "Sobreatico" just above the sixth floor. (Not all buildings will have all of these floor names).
                – Aaron F
                Sep 4 at 12:20




                2




                2




                Nothing Wirthian is inherited from ALGOL-68.
                – philipxy
                Sep 6 at 2:35




                Nothing Wirthian is inherited from ALGOL-68.
                – philipxy
                Sep 6 at 2:35




                2




                2




                +1, but this is only half the answer. The other half is that in the 70's C made the choice to directly support only indexing arrays from 0, as this made the compiler simplest (which was really C's primary design goal). Because C compilers were so simple, they were easy to make and put on any machine, and as a result of this and a few other bits of historical luck, C became super popular. As a result of that, a whole host of other languages took their lead from C.
                – T.E.D.
                Sep 6 at 14:32




                +1, but this is only half the answer. The other half is that in the 70's C made the choice to directly support only indexing arrays from 0, as this made the compiler simplest (which was really C's primary design goal). Because C compilers were so simple, they were easy to make and put on any machine, and as a result of this and a few other bits of historical luck, C became super popular. As a result of that, a whole host of other languages took their lead from C.
                – T.E.D.
                Sep 6 at 14:32










                up vote
                18
                down vote













                When I've explained this to beginning students, I don't stray far from your third reason, though I agree that the beginning of arrays is early to introduce the concept of memory addresses. Among other things, that invites about your variable, c, when the only variable they need to worry about is i.



                Instead of memory addresses, I talk about distances from the start. I've given a sample below using paper and a pencil as a reference point, though in my classroom I use the whiteboard and hold a marker. All of the numbers are in little boxes, and together they form a rectangle.




                Look at the list of numbers on the paper. We all know about ordinal numbers, "first", "second", "third", and so forth. But when we program, we actually refer to the list numbers a slightly different way, as 0, 1, and 2. This is called 0-based indexing, and the reasons for it don't matter right now. What matters is that the first item on the list is actually item 0.



                Honestly, that's all you need to know to use arrays correctly. But if you want a hint about why we actually do this, you can think about zero-based indexing as the distance from the head of the array.



                So, if I'm at the head of the array, how many moves do I have to make to read the first number? No moves, I'm already there. What about the second number? I make one move to get there. The fourth number? One, two, three moves.



                Beyond the most important fact that we start counting from 0, thinking about it as "moves" is actually a good way to think about array indexes, because when we come back to this topic later, you'll see that the distance from the head turns out to be an important concept for understanding a lot of things a computer does. Don't worry we'll get there soon enough.



                So, for now, what is the index for this spot in the array? (I point to a random index, wait for the students to arrive at the answer.) Good, well done. Now, moving on to ...







                share|improve this answer






















                • 'cardinal numbers, "first", "second", "third"'. These are ordinals, not cardinals. Cardinals count amount. Ordinals count order.
                  – Potato44
                  Sep 3 at 12:43










                • @Potato44 Yes, they are. What an embarrassing error! Thanks for pointing it out, I'll fix it now.
                  – Ben I.♦
                  Sep 3 at 14:49






                • 2




                  Ah, but some of us are willing to say zero-th, also.
                  – Buffy
                  Sep 3 at 14:54














                up vote
                18
                down vote













                When I've explained this to beginning students, I don't stray far from your third reason, though I agree that the beginning of arrays is early to introduce the concept of memory addresses. Among other things, that invites about your variable, c, when the only variable they need to worry about is i.



                Instead of memory addresses, I talk about distances from the start. I've given a sample below using paper and a pencil as a reference point, though in my classroom I use the whiteboard and hold a marker. All of the numbers are in little boxes, and together they form a rectangle.




                Look at the list of numbers on the paper. We all know about ordinal numbers, "first", "second", "third", and so forth. But when we program, we actually refer to the list numbers a slightly different way, as 0, 1, and 2. This is called 0-based indexing, and the reasons for it don't matter right now. What matters is that the first item on the list is actually item 0.



                Honestly, that's all you need to know to use arrays correctly. But if you want a hint about why we actually do this, you can think about zero-based indexing as the distance from the head of the array.



                So, if I'm at the head of the array, how many moves do I have to make to read the first number? No moves, I'm already there. What about the second number? I make one move to get there. The fourth number? One, two, three moves.



                Beyond the most important fact that we start counting from 0, thinking about it as "moves" is actually a good way to think about array indexes, because when we come back to this topic later, you'll see that the distance from the head turns out to be an important concept for understanding a lot of things a computer does. Don't worry we'll get there soon enough.



                So, for now, what is the index for this spot in the array? (I point to a random index, wait for the students to arrive at the answer.) Good, well done. Now, moving on to ...







                share|improve this answer






















                • 'cardinal numbers, "first", "second", "third"'. These are ordinals, not cardinals. Cardinals count amount. Ordinals count order.
                  – Potato44
                  Sep 3 at 12:43










                • @Potato44 Yes, they are. What an embarrassing error! Thanks for pointing it out, I'll fix it now.
                  – Ben I.♦
                  Sep 3 at 14:49






                • 2




                  Ah, but some of us are willing to say zero-th, also.
                  – Buffy
                  Sep 3 at 14:54












                up vote
                18
                down vote










                up vote
                18
                down vote









                When I've explained this to beginning students, I don't stray far from your third reason, though I agree that the beginning of arrays is early to introduce the concept of memory addresses. Among other things, that invites about your variable, c, when the only variable they need to worry about is i.



                Instead of memory addresses, I talk about distances from the start. I've given a sample below using paper and a pencil as a reference point, though in my classroom I use the whiteboard and hold a marker. All of the numbers are in little boxes, and together they form a rectangle.




                Look at the list of numbers on the paper. We all know about ordinal numbers, "first", "second", "third", and so forth. But when we program, we actually refer to the list numbers a slightly different way, as 0, 1, and 2. This is called 0-based indexing, and the reasons for it don't matter right now. What matters is that the first item on the list is actually item 0.



                Honestly, that's all you need to know to use arrays correctly. But if you want a hint about why we actually do this, you can think about zero-based indexing as the distance from the head of the array.



                So, if I'm at the head of the array, how many moves do I have to make to read the first number? No moves, I'm already there. What about the second number? I make one move to get there. The fourth number? One, two, three moves.



                Beyond the most important fact that we start counting from 0, thinking about it as "moves" is actually a good way to think about array indexes, because when we come back to this topic later, you'll see that the distance from the head turns out to be an important concept for understanding a lot of things a computer does. Don't worry we'll get there soon enough.



                So, for now, what is the index for this spot in the array? (I point to a random index, wait for the students to arrive at the answer.) Good, well done. Now, moving on to ...







                share|improve this answer














                When I've explained this to beginning students, I don't stray far from your third reason, though I agree that the beginning of arrays is early to introduce the concept of memory addresses. Among other things, that invites about your variable, c, when the only variable they need to worry about is i.



                Instead of memory addresses, I talk about distances from the start. I've given a sample below using paper and a pencil as a reference point, though in my classroom I use the whiteboard and hold a marker. All of the numbers are in little boxes, and together they form a rectangle.




                Look at the list of numbers on the paper. We all know about ordinal numbers, "first", "second", "third", and so forth. But when we program, we actually refer to the list numbers a slightly different way, as 0, 1, and 2. This is called 0-based indexing, and the reasons for it don't matter right now. What matters is that the first item on the list is actually item 0.



                Honestly, that's all you need to know to use arrays correctly. But if you want a hint about why we actually do this, you can think about zero-based indexing as the distance from the head of the array.



                So, if I'm at the head of the array, how many moves do I have to make to read the first number? No moves, I'm already there. What about the second number? I make one move to get there. The fourth number? One, two, three moves.



                Beyond the most important fact that we start counting from 0, thinking about it as "moves" is actually a good way to think about array indexes, because when we come back to this topic later, you'll see that the distance from the head turns out to be an important concept for understanding a lot of things a computer does. Don't worry we'll get there soon enough.



                So, for now, what is the index for this spot in the array? (I point to a random index, wait for the students to arrive at the answer.) Good, well done. Now, moving on to ...








                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Sep 3 at 14:50

























                answered Sep 3 at 3:47









                Ben I.♦

                16.9k739102




                16.9k739102











                • 'cardinal numbers, "first", "second", "third"'. These are ordinals, not cardinals. Cardinals count amount. Ordinals count order.
                  – Potato44
                  Sep 3 at 12:43










                • @Potato44 Yes, they are. What an embarrassing error! Thanks for pointing it out, I'll fix it now.
                  – Ben I.♦
                  Sep 3 at 14:49






                • 2




                  Ah, but some of us are willing to say zero-th, also.
                  – Buffy
                  Sep 3 at 14:54
















                • 'cardinal numbers, "first", "second", "third"'. These are ordinals, not cardinals. Cardinals count amount. Ordinals count order.
                  – Potato44
                  Sep 3 at 12:43










                • @Potato44 Yes, they are. What an embarrassing error! Thanks for pointing it out, I'll fix it now.
                  – Ben I.♦
                  Sep 3 at 14:49






                • 2




                  Ah, but some of us are willing to say zero-th, also.
                  – Buffy
                  Sep 3 at 14:54















                'cardinal numbers, "first", "second", "third"'. These are ordinals, not cardinals. Cardinals count amount. Ordinals count order.
                – Potato44
                Sep 3 at 12:43




                'cardinal numbers, "first", "second", "third"'. These are ordinals, not cardinals. Cardinals count amount. Ordinals count order.
                – Potato44
                Sep 3 at 12:43












                @Potato44 Yes, they are. What an embarrassing error! Thanks for pointing it out, I'll fix it now.
                – Ben I.♦
                Sep 3 at 14:49




                @Potato44 Yes, they are. What an embarrassing error! Thanks for pointing it out, I'll fix it now.
                – Ben I.♦
                Sep 3 at 14:49




                2




                2




                Ah, but some of us are willing to say zero-th, also.
                – Buffy
                Sep 3 at 14:54




                Ah, but some of us are willing to say zero-th, also.
                – Buffy
                Sep 3 at 14:54










                up vote
                9
                down vote














                In computer science, we usually count starting from 0.




                In programming or in (theoretical) computer science?



                In Programming



                In C programming language you count from 0 to (N-1). And of course in languages which are influenced by C: Java, JavaScript, PHP, C#, C++...



                You already named the reason for this:




                In C, we can use *a to access the first element of array a.




                ... and because a[i] is the same as *(a+i) the first index of the array must have the index 0.




                This doesn't seem very relevant today for a new student who isn't programming in C.




                In many (most?) other programming languages (Basic, Pascal and Matlab for example) you typically count from 1 to N, not from 0 to (N-1).



                (For example in for loops.)



                As already said in the other answers there often is the possibility to define the index of the first element of an array freely (e.g. in Pascal) or the index of the first element is even fixed to 1 (e.g. in Matlab).



                These languages don't have pointer arithmetic.



                In (theoretical) computer science



                I have no idea if they count from 0 there.



                However I think that the programming languages which are used most influence the way of thinking in theoretical computer science, too.






                share|improve this answer


















                • 1




                  I think the C equivalence of arr[i] = *(arr+i) follows from its choice of zero-based indexing, not the other way around. But good point that having pointer arithmetic at all makes zero-based indexing much more natural, and that most still-used languages with 1-based indexing don't have that. C started as a portable assembly language, so it's totally natural that it works like asm in this regard.
                  – Peter Cordes
                  Sep 4 at 0:04







                • 1




                  @PeterCordes I'm not sure. But I think the fact that the array operator can be used for pointer arithmetic at all (such as ptr[-5]) played a role in defining that ptr[i] is equal to *(ptr+i).
                  – Martin Rosenau
                  Sep 4 at 5:53






                • 3




                  The advantage of zero-based indexing becomes even more apparent when you need to map a 2D matrix to a linear array.
                  – 200_success
                  Sep 4 at 18:13






                • 1




                  This is the missing half of Jorg's answer, which together make the correct answer. C made the choice to only support indexing arrays from 0, and after it became popular it influenced the design of a lot of other languages. However, its quite likely most languages don't force a 0-based index, and some people thinking this is a computer language thing, (or worse yet, a Computer Science thing) is nothing more than myopia.
                  – T.E.D.
                  Sep 6 at 14:37










                • Most index from 0, including BASIC (though I'm sure there's a variant which starts at 1). Here's a table.
                  – Schwern
                  3 hours ago














                up vote
                9
                down vote














                In computer science, we usually count starting from 0.




                In programming or in (theoretical) computer science?



                In Programming



                In C programming language you count from 0 to (N-1). And of course in languages which are influenced by C: Java, JavaScript, PHP, C#, C++...



                You already named the reason for this:




                In C, we can use *a to access the first element of array a.




                ... and because a[i] is the same as *(a+i) the first index of the array must have the index 0.




                This doesn't seem very relevant today for a new student who isn't programming in C.




                In many (most?) other programming languages (Basic, Pascal and Matlab for example) you typically count from 1 to N, not from 0 to (N-1).



                (For example in for loops.)



                As already said in the other answers there often is the possibility to define the index of the first element of an array freely (e.g. in Pascal) or the index of the first element is even fixed to 1 (e.g. in Matlab).



                These languages don't have pointer arithmetic.



                In (theoretical) computer science



                I have no idea if they count from 0 there.



                However I think that the programming languages which are used most influence the way of thinking in theoretical computer science, too.






                share|improve this answer


















                • 1




                  I think the C equivalence of arr[i] = *(arr+i) follows from its choice of zero-based indexing, not the other way around. But good point that having pointer arithmetic at all makes zero-based indexing much more natural, and that most still-used languages with 1-based indexing don't have that. C started as a portable assembly language, so it's totally natural that it works like asm in this regard.
                  – Peter Cordes
                  Sep 4 at 0:04







                • 1




                  @PeterCordes I'm not sure. But I think the fact that the array operator can be used for pointer arithmetic at all (such as ptr[-5]) played a role in defining that ptr[i] is equal to *(ptr+i).
                  – Martin Rosenau
                  Sep 4 at 5:53






                • 3




                  The advantage of zero-based indexing becomes even more apparent when you need to map a 2D matrix to a linear array.
                  – 200_success
                  Sep 4 at 18:13






                • 1




                  This is the missing half of Jorg's answer, which together make the correct answer. C made the choice to only support indexing arrays from 0, and after it became popular it influenced the design of a lot of other languages. However, its quite likely most languages don't force a 0-based index, and some people thinking this is a computer language thing, (or worse yet, a Computer Science thing) is nothing more than myopia.
                  – T.E.D.
                  Sep 6 at 14:37










                • Most index from 0, including BASIC (though I'm sure there's a variant which starts at 1). Here's a table.
                  – Schwern
                  3 hours ago












                up vote
                9
                down vote










                up vote
                9
                down vote










                In computer science, we usually count starting from 0.




                In programming or in (theoretical) computer science?



                In Programming



                In C programming language you count from 0 to (N-1). And of course in languages which are influenced by C: Java, JavaScript, PHP, C#, C++...



                You already named the reason for this:




                In C, we can use *a to access the first element of array a.




                ... and because a[i] is the same as *(a+i) the first index of the array must have the index 0.




                This doesn't seem very relevant today for a new student who isn't programming in C.




                In many (most?) other programming languages (Basic, Pascal and Matlab for example) you typically count from 1 to N, not from 0 to (N-1).



                (For example in for loops.)



                As already said in the other answers there often is the possibility to define the index of the first element of an array freely (e.g. in Pascal) or the index of the first element is even fixed to 1 (e.g. in Matlab).



                These languages don't have pointer arithmetic.



                In (theoretical) computer science



                I have no idea if they count from 0 there.



                However I think that the programming languages which are used most influence the way of thinking in theoretical computer science, too.






                share|improve this answer















                In computer science, we usually count starting from 0.




                In programming or in (theoretical) computer science?



                In Programming



                In C programming language you count from 0 to (N-1). And of course in languages which are influenced by C: Java, JavaScript, PHP, C#, C++...



                You already named the reason for this:




                In C, we can use *a to access the first element of array a.




                ... and because a[i] is the same as *(a+i) the first index of the array must have the index 0.




                This doesn't seem very relevant today for a new student who isn't programming in C.




                In many (most?) other programming languages (Basic, Pascal and Matlab for example) you typically count from 1 to N, not from 0 to (N-1).



                (For example in for loops.)



                As already said in the other answers there often is the possibility to define the index of the first element of an array freely (e.g. in Pascal) or the index of the first element is even fixed to 1 (e.g. in Matlab).



                These languages don't have pointer arithmetic.



                In (theoretical) computer science



                I have no idea if they count from 0 there.



                However I think that the programming languages which are used most influence the way of thinking in theoretical computer science, too.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Sep 3 at 11:04

























                answered Sep 3 at 10:56









                Martin Rosenau

                1912




                1912







                • 1




                  I think the C equivalence of arr[i] = *(arr+i) follows from its choice of zero-based indexing, not the other way around. But good point that having pointer arithmetic at all makes zero-based indexing much more natural, and that most still-used languages with 1-based indexing don't have that. C started as a portable assembly language, so it's totally natural that it works like asm in this regard.
                  – Peter Cordes
                  Sep 4 at 0:04







                • 1




                  @PeterCordes I'm not sure. But I think the fact that the array operator can be used for pointer arithmetic at all (such as ptr[-5]) played a role in defining that ptr[i] is equal to *(ptr+i).
                  – Martin Rosenau
                  Sep 4 at 5:53






                • 3




                  The advantage of zero-based indexing becomes even more apparent when you need to map a 2D matrix to a linear array.
                  – 200_success
                  Sep 4 at 18:13






                • 1




                  This is the missing half of Jorg's answer, which together make the correct answer. C made the choice to only support indexing arrays from 0, and after it became popular it influenced the design of a lot of other languages. However, its quite likely most languages don't force a 0-based index, and some people thinking this is a computer language thing, (or worse yet, a Computer Science thing) is nothing more than myopia.
                  – T.E.D.
                  Sep 6 at 14:37










                • Most index from 0, including BASIC (though I'm sure there's a variant which starts at 1). Here's a table.
                  – Schwern
                  3 hours ago












                • 1




                  I think the C equivalence of arr[i] = *(arr+i) follows from its choice of zero-based indexing, not the other way around. But good point that having pointer arithmetic at all makes zero-based indexing much more natural, and that most still-used languages with 1-based indexing don't have that. C started as a portable assembly language, so it's totally natural that it works like asm in this regard.
                  – Peter Cordes
                  Sep 4 at 0:04







                • 1




                  @PeterCordes I'm not sure. But I think the fact that the array operator can be used for pointer arithmetic at all (such as ptr[-5]) played a role in defining that ptr[i] is equal to *(ptr+i).
                  – Martin Rosenau
                  Sep 4 at 5:53






                • 3




                  The advantage of zero-based indexing becomes even more apparent when you need to map a 2D matrix to a linear array.
                  – 200_success
                  Sep 4 at 18:13






                • 1




                  This is the missing half of Jorg's answer, which together make the correct answer. C made the choice to only support indexing arrays from 0, and after it became popular it influenced the design of a lot of other languages. However, its quite likely most languages don't force a 0-based index, and some people thinking this is a computer language thing, (or worse yet, a Computer Science thing) is nothing more than myopia.
                  – T.E.D.
                  Sep 6 at 14:37










                • Most index from 0, including BASIC (though I'm sure there's a variant which starts at 1). Here's a table.
                  – Schwern
                  3 hours ago







                1




                1




                I think the C equivalence of arr[i] = *(arr+i) follows from its choice of zero-based indexing, not the other way around. But good point that having pointer arithmetic at all makes zero-based indexing much more natural, and that most still-used languages with 1-based indexing don't have that. C started as a portable assembly language, so it's totally natural that it works like asm in this regard.
                – Peter Cordes
                Sep 4 at 0:04





                I think the C equivalence of arr[i] = *(arr+i) follows from its choice of zero-based indexing, not the other way around. But good point that having pointer arithmetic at all makes zero-based indexing much more natural, and that most still-used languages with 1-based indexing don't have that. C started as a portable assembly language, so it's totally natural that it works like asm in this regard.
                – Peter Cordes
                Sep 4 at 0:04





                1




                1




                @PeterCordes I'm not sure. But I think the fact that the array operator can be used for pointer arithmetic at all (such as ptr[-5]) played a role in defining that ptr[i] is equal to *(ptr+i).
                – Martin Rosenau
                Sep 4 at 5:53




                @PeterCordes I'm not sure. But I think the fact that the array operator can be used for pointer arithmetic at all (such as ptr[-5]) played a role in defining that ptr[i] is equal to *(ptr+i).
                – Martin Rosenau
                Sep 4 at 5:53




                3




                3




                The advantage of zero-based indexing becomes even more apparent when you need to map a 2D matrix to a linear array.
                – 200_success
                Sep 4 at 18:13




                The advantage of zero-based indexing becomes even more apparent when you need to map a 2D matrix to a linear array.
                – 200_success
                Sep 4 at 18:13




                1




                1




                This is the missing half of Jorg's answer, which together make the correct answer. C made the choice to only support indexing arrays from 0, and after it became popular it influenced the design of a lot of other languages. However, its quite likely most languages don't force a 0-based index, and some people thinking this is a computer language thing, (or worse yet, a Computer Science thing) is nothing more than myopia.
                – T.E.D.
                Sep 6 at 14:37




                This is the missing half of Jorg's answer, which together make the correct answer. C made the choice to only support indexing arrays from 0, and after it became popular it influenced the design of a lot of other languages. However, its quite likely most languages don't force a 0-based index, and some people thinking this is a computer language thing, (or worse yet, a Computer Science thing) is nothing more than myopia.
                – T.E.D.
                Sep 6 at 14:37












                Most index from 0, including BASIC (though I'm sure there's a variant which starts at 1). Here's a table.
                – Schwern
                3 hours ago




                Most index from 0, including BASIC (though I'm sure there's a variant which starts at 1). Here's a table.
                – Schwern
                3 hours ago










                up vote
                8
                down vote













                In languages such as C, the first item in an array has an offset of zero from the pointer. If the size of your objects are 4 bytes, the next item has an offset of 1 x 4 bytes.



                Index Size Offset
                0 4 base + 0
                1 4 base + 4
                2 4 base + 8
                3 4 base + 12


                And so on.



                If the items were indexed on natural counting, there would have to be an adjustment made by both the computer and the programmer to find the location of the item in memory. Mistakes would be made by having this additional step, particularly on the human side of the process. It's easier, although slightly unintuitive, to use zero-based indexing.






                share|improve this answer
















                • 3




                  Welcome to Computer Science Educators! Isn't this just a restatement of OP's third bullet?
                  – Ben I.♦
                  Sep 3 at 12:16










                • yes, the pointer (which is the array) contains the 1st element, then you add 1 to get the next element etc. In assembler we were taught indexing to access arrays, so moving to C it all made simple sense.
                  – WendyG
                  Sep 3 at 12:17






                • 1




                  @BenI. My answer addresses the human side of "making it easy".
                  – CJ Dennis
                  Sep 3 at 12:20










                • Welcome to the community, please read the question. The OP states in the question that this explanation is unsatisfactory, for the intended audience.
                  – ctrl-alt-delor
                  Sep 4 at 7:58










                • Keep in mind that C arrays are rather plain. In many languages, the pointer refers not to the first item, but to things such as the length of the array. And yet both 0-indexed and 1-indexed arrays exist. Indeed, you could use your argument to argue that arrays should start at 1, because that would allow you to store metadata in the "0 offset".
                  – Luaan
                  Sep 5 at 9:05














                up vote
                8
                down vote













                In languages such as C, the first item in an array has an offset of zero from the pointer. If the size of your objects are 4 bytes, the next item has an offset of 1 x 4 bytes.



                Index Size Offset
                0 4 base + 0
                1 4 base + 4
                2 4 base + 8
                3 4 base + 12


                And so on.



                If the items were indexed on natural counting, there would have to be an adjustment made by both the computer and the programmer to find the location of the item in memory. Mistakes would be made by having this additional step, particularly on the human side of the process. It's easier, although slightly unintuitive, to use zero-based indexing.






                share|improve this answer
















                • 3




                  Welcome to Computer Science Educators! Isn't this just a restatement of OP's third bullet?
                  – Ben I.♦
                  Sep 3 at 12:16










                • yes, the pointer (which is the array) contains the 1st element, then you add 1 to get the next element etc. In assembler we were taught indexing to access arrays, so moving to C it all made simple sense.
                  – WendyG
                  Sep 3 at 12:17






                • 1




                  @BenI. My answer addresses the human side of "making it easy".
                  – CJ Dennis
                  Sep 3 at 12:20










                • Welcome to the community, please read the question. The OP states in the question that this explanation is unsatisfactory, for the intended audience.
                  – ctrl-alt-delor
                  Sep 4 at 7:58










                • Keep in mind that C arrays are rather plain. In many languages, the pointer refers not to the first item, but to things such as the length of the array. And yet both 0-indexed and 1-indexed arrays exist. Indeed, you could use your argument to argue that arrays should start at 1, because that would allow you to store metadata in the "0 offset".
                  – Luaan
                  Sep 5 at 9:05












                up vote
                8
                down vote










                up vote
                8
                down vote









                In languages such as C, the first item in an array has an offset of zero from the pointer. If the size of your objects are 4 bytes, the next item has an offset of 1 x 4 bytes.



                Index Size Offset
                0 4 base + 0
                1 4 base + 4
                2 4 base + 8
                3 4 base + 12


                And so on.



                If the items were indexed on natural counting, there would have to be an adjustment made by both the computer and the programmer to find the location of the item in memory. Mistakes would be made by having this additional step, particularly on the human side of the process. It's easier, although slightly unintuitive, to use zero-based indexing.






                share|improve this answer












                In languages such as C, the first item in an array has an offset of zero from the pointer. If the size of your objects are 4 bytes, the next item has an offset of 1 x 4 bytes.



                Index Size Offset
                0 4 base + 0
                1 4 base + 4
                2 4 base + 8
                3 4 base + 12


                And so on.



                If the items were indexed on natural counting, there would have to be an adjustment made by both the computer and the programmer to find the location of the item in memory. Mistakes would be made by having this additional step, particularly on the human side of the process. It's easier, although slightly unintuitive, to use zero-based indexing.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Sep 3 at 7:12









                CJ Dennis

                1892




                1892







                • 3




                  Welcome to Computer Science Educators! Isn't this just a restatement of OP's third bullet?
                  – Ben I.♦
                  Sep 3 at 12:16










                • yes, the pointer (which is the array) contains the 1st element, then you add 1 to get the next element etc. In assembler we were taught indexing to access arrays, so moving to C it all made simple sense.
                  – WendyG
                  Sep 3 at 12:17






                • 1




                  @BenI. My answer addresses the human side of "making it easy".
                  – CJ Dennis
                  Sep 3 at 12:20










                • Welcome to the community, please read the question. The OP states in the question that this explanation is unsatisfactory, for the intended audience.
                  – ctrl-alt-delor
                  Sep 4 at 7:58










                • Keep in mind that C arrays are rather plain. In many languages, the pointer refers not to the first item, but to things such as the length of the array. And yet both 0-indexed and 1-indexed arrays exist. Indeed, you could use your argument to argue that arrays should start at 1, because that would allow you to store metadata in the "0 offset".
                  – Luaan
                  Sep 5 at 9:05












                • 3




                  Welcome to Computer Science Educators! Isn't this just a restatement of OP's third bullet?
                  – Ben I.♦
                  Sep 3 at 12:16










                • yes, the pointer (which is the array) contains the 1st element, then you add 1 to get the next element etc. In assembler we were taught indexing to access arrays, so moving to C it all made simple sense.
                  – WendyG
                  Sep 3 at 12:17






                • 1




                  @BenI. My answer addresses the human side of "making it easy".
                  – CJ Dennis
                  Sep 3 at 12:20










                • Welcome to the community, please read the question. The OP states in the question that this explanation is unsatisfactory, for the intended audience.
                  – ctrl-alt-delor
                  Sep 4 at 7:58










                • Keep in mind that C arrays are rather plain. In many languages, the pointer refers not to the first item, but to things such as the length of the array. And yet both 0-indexed and 1-indexed arrays exist. Indeed, you could use your argument to argue that arrays should start at 1, because that would allow you to store metadata in the "0 offset".
                  – Luaan
                  Sep 5 at 9:05







                3




                3




                Welcome to Computer Science Educators! Isn't this just a restatement of OP's third bullet?
                – Ben I.♦
                Sep 3 at 12:16




                Welcome to Computer Science Educators! Isn't this just a restatement of OP's third bullet?
                – Ben I.♦
                Sep 3 at 12:16












                yes, the pointer (which is the array) contains the 1st element, then you add 1 to get the next element etc. In assembler we were taught indexing to access arrays, so moving to C it all made simple sense.
                – WendyG
                Sep 3 at 12:17




                yes, the pointer (which is the array) contains the 1st element, then you add 1 to get the next element etc. In assembler we were taught indexing to access arrays, so moving to C it all made simple sense.
                – WendyG
                Sep 3 at 12:17




                1




                1




                @BenI. My answer addresses the human side of "making it easy".
                – CJ Dennis
                Sep 3 at 12:20




                @BenI. My answer addresses the human side of "making it easy".
                – CJ Dennis
                Sep 3 at 12:20












                Welcome to the community, please read the question. The OP states in the question that this explanation is unsatisfactory, for the intended audience.
                – ctrl-alt-delor
                Sep 4 at 7:58




                Welcome to the community, please read the question. The OP states in the question that this explanation is unsatisfactory, for the intended audience.
                – ctrl-alt-delor
                Sep 4 at 7:58












                Keep in mind that C arrays are rather plain. In many languages, the pointer refers not to the first item, but to things such as the length of the array. And yet both 0-indexed and 1-indexed arrays exist. Indeed, you could use your argument to argue that arrays should start at 1, because that would allow you to store metadata in the "0 offset".
                – Luaan
                Sep 5 at 9:05




                Keep in mind that C arrays are rather plain. In many languages, the pointer refers not to the first item, but to things such as the length of the array. And yet both 0-indexed and 1-indexed arrays exist. Indeed, you could use your argument to argue that arrays should start at 1, because that would allow you to store metadata in the "0 offset".
                – Luaan
                Sep 5 at 9:05










                up vote
                6
                down vote













                Simply put, we do not count from zero, we shift from zero



                You can think C as a neat way to not write different assembly for every architecture/machine/processor in existence. Instead, take a simple and short macro-like language for a abstracted machine, compile that, and brk() your way on abstracted memory.



                But abstracted memory is only a sequence of bytes, you need a way to refer to specific segments. Enter pointers. But to not make every item a allocation (think of a string where every char is separately allocated) the next step is "lists". The most compact list1 is a pointer to the first element, and then put every other element in adjacent slots.



                Every element is, then, indexed as shift from first. And because that, the shift index starts from zero.




                1 This is from a era when you need entire reunions to decide if is worth spend whooping 52 bytes to have your system know about leap years...






                share|improve this answer


























                  up vote
                  6
                  down vote













                  Simply put, we do not count from zero, we shift from zero



                  You can think C as a neat way to not write different assembly for every architecture/machine/processor in existence. Instead, take a simple and short macro-like language for a abstracted machine, compile that, and brk() your way on abstracted memory.



                  But abstracted memory is only a sequence of bytes, you need a way to refer to specific segments. Enter pointers. But to not make every item a allocation (think of a string where every char is separately allocated) the next step is "lists". The most compact list1 is a pointer to the first element, and then put every other element in adjacent slots.



                  Every element is, then, indexed as shift from first. And because that, the shift index starts from zero.




                  1 This is from a era when you need entire reunions to decide if is worth spend whooping 52 bytes to have your system know about leap years...






                  share|improve this answer
























                    up vote
                    6
                    down vote










                    up vote
                    6
                    down vote









                    Simply put, we do not count from zero, we shift from zero



                    You can think C as a neat way to not write different assembly for every architecture/machine/processor in existence. Instead, take a simple and short macro-like language for a abstracted machine, compile that, and brk() your way on abstracted memory.



                    But abstracted memory is only a sequence of bytes, you need a way to refer to specific segments. Enter pointers. But to not make every item a allocation (think of a string where every char is separately allocated) the next step is "lists". The most compact list1 is a pointer to the first element, and then put every other element in adjacent slots.



                    Every element is, then, indexed as shift from first. And because that, the shift index starts from zero.




                    1 This is from a era when you need entire reunions to decide if is worth spend whooping 52 bytes to have your system know about leap years...






                    share|improve this answer














                    Simply put, we do not count from zero, we shift from zero



                    You can think C as a neat way to not write different assembly for every architecture/machine/processor in existence. Instead, take a simple and short macro-like language for a abstracted machine, compile that, and brk() your way on abstracted memory.



                    But abstracted memory is only a sequence of bytes, you need a way to refer to specific segments. Enter pointers. But to not make every item a allocation (think of a string where every char is separately allocated) the next step is "lists". The most compact list1 is a pointer to the first element, and then put every other element in adjacent slots.



                    Every element is, then, indexed as shift from first. And because that, the shift index starts from zero.




                    1 This is from a era when you need entire reunions to decide if is worth spend whooping 52 bytes to have your system know about leap years...







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited yesterday

























                    answered Sep 3 at 13:55









                    André LFS Bacci

                    1612




                    1612




















                        up vote
                        5
                        down vote













                        I will try to answer, without reference to low-level programming (or any programming language), without mention of history, or much maths.



                        As already stated in some answers, we do not count from zero (using the value 0 to represent 1, and 1 to represent 2 (Usually)). So what do we do?



                        We measure from zero. If I give you a ruler, and ask you to measure something, you measure from zero. If I ask you to tell me how far a cell in an array is from the start, then you measure from zero (the first cell is zero from the start: it is at the start), the 2nd cell is 1 from the start.






                        share|improve this answer


















                        • 3




                          We absolutely count from zero. If you want to count sheep hopping over a fence, you initialize the sheep_count variable to 0, not 1. If no sheep appear, you must report that zero value as the count.
                          – Kaz
                          Sep 6 at 0:03















                        up vote
                        5
                        down vote













                        I will try to answer, without reference to low-level programming (or any programming language), without mention of history, or much maths.



                        As already stated in some answers, we do not count from zero (using the value 0 to represent 1, and 1 to represent 2 (Usually)). So what do we do?



                        We measure from zero. If I give you a ruler, and ask you to measure something, you measure from zero. If I ask you to tell me how far a cell in an array is from the start, then you measure from zero (the first cell is zero from the start: it is at the start), the 2nd cell is 1 from the start.






                        share|improve this answer


















                        • 3




                          We absolutely count from zero. If you want to count sheep hopping over a fence, you initialize the sheep_count variable to 0, not 1. If no sheep appear, you must report that zero value as the count.
                          – Kaz
                          Sep 6 at 0:03













                        up vote
                        5
                        down vote










                        up vote
                        5
                        down vote









                        I will try to answer, without reference to low-level programming (or any programming language), without mention of history, or much maths.



                        As already stated in some answers, we do not count from zero (using the value 0 to represent 1, and 1 to represent 2 (Usually)). So what do we do?



                        We measure from zero. If I give you a ruler, and ask you to measure something, you measure from zero. If I ask you to tell me how far a cell in an array is from the start, then you measure from zero (the first cell is zero from the start: it is at the start), the 2nd cell is 1 from the start.






                        share|improve this answer














                        I will try to answer, without reference to low-level programming (or any programming language), without mention of history, or much maths.



                        As already stated in some answers, we do not count from zero (using the value 0 to represent 1, and 1 to represent 2 (Usually)). So what do we do?



                        We measure from zero. If I give you a ruler, and ask you to measure something, you measure from zero. If I ask you to tell me how far a cell in an array is from the start, then you measure from zero (the first cell is zero from the start: it is at the start), the 2nd cell is 1 from the start.







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Sep 6 at 8:58

























                        answered Sep 3 at 22:31









                        ctrl-alt-delor

                        6,89831446




                        6,89831446







                        • 3




                          We absolutely count from zero. If you want to count sheep hopping over a fence, you initialize the sheep_count variable to 0, not 1. If no sheep appear, you must report that zero value as the count.
                          – Kaz
                          Sep 6 at 0:03













                        • 3




                          We absolutely count from zero. If you want to count sheep hopping over a fence, you initialize the sheep_count variable to 0, not 1. If no sheep appear, you must report that zero value as the count.
                          – Kaz
                          Sep 6 at 0:03








                        3




                        3




                        We absolutely count from zero. If you want to count sheep hopping over a fence, you initialize the sheep_count variable to 0, not 1. If no sheep appear, you must report that zero value as the count.
                        – Kaz
                        Sep 6 at 0:03





                        We absolutely count from zero. If you want to count sheep hopping over a fence, you initialize the sheep_count variable to 0, not 1. If no sheep appear, you must report that zero value as the count.
                        – Kaz
                        Sep 6 at 0:03











                        up vote
                        4
                        down vote













                        From time to time I have had to do numerical work in MATLAB and the 1-based indexing always stuck out like a sore thumb, so I have a few examples I can provide where 0-based indexing is advantageous.



                        Modular access



                        This is the simplest example. If you want to "wrap around" an array, the modulus operator works like a charm. (And don't say "what if the modulus operator were defined from 1 to n instead"—that would be mathematically ludicrous.)



                        str = "This is the song that never ends... "
                        position = 300
                        charAtPosition = str[position % (str.length)]


                        Real world examples of this might include working with days of the week, generating repeating gradients, or coming up with a predicable item from a small list given a large ID number.



                        Discretisation



                        Let's say you want to generate a histogram of heights. The first "bucket" is 50cm-70cm. The next is 70-90cm. And so on up to 210cm.



                        Using zero-based indexing, the code looks like



                        bucket[floor((height - 50) / 20)] += 1


                        With 1-based indexing, it looks like



                        bucket[ceil((height - 50) / 20)] += 1
                        or
                        bucket[floor((height - 50) / 20) + 1] += 1


                        (the two have slightly different semantics). So you can either have a stray "+ 1" or use the ceil function. I believe the floor function is more "natural" than the ceil function since floor(a/b) is the quotient when you divide a by b; for this reason integer division often suffices in such calculations whereas the ceil version would be more complex. Also, if you wanted the buckets in reverse order, this is 0-based indexing:



                        BUCKETS = (210 - 50) / 20 - 1

                        #intuitive because BUCKETS - 1 is the highest index
                        bucket[(BUCKETS - 1) - floor((height - 50) / 20)] += 1


                        versus



                        #not intuitive... what does BUCKETS + 1 represent?
                        bucket[BUCKETS + 1 - ceil((height - 50) / 20)] += 1
                        or
                        #not intuitive... how come a forwards list needs "+ 1" but
                        #backwards list doesn't?
                        bucket[BUCKETS - floor((height - 50) / 20)] += 1


                        Change of Coordinate Systems



                        This is related to the above "direction flip". Although I will use a 1 dimensional example, this also applies to 2D and higher dimensional translations, rotations, and scaling.



                        Let's suppose, for each slot in the top row you want to find find the best fitting slot in the bottom row. (This often occurs when you want to efficiently reduce the quality of some data; image resizing is a 2D version of this).



                        With 0-based indexing:



                        0-based indexing



                        #intuitive because the centre of slot[0] is actually at x co-ordinate 0.5
                        nearest = floor((original + 0.5) / 5 * 7);


                        With 1-based indexing:



                        enter image description here



                        #Why -0.5? Can you explain? And then we need to "fix" it with a +1
                        nearest = floor((original - 0.5) / 5 * 7) + 1;


                        Nice Invariants



                        In order to prove that programs work correctly, computer scientists use the concept of an "invariant"—a property that is guaranteed to be true at a certain place in the code, no matter the program flow up to that point.



                        This is not just a theoretical concept. Even if invariants are not explicitly provided, code that has nice invariants tends to be easier to think about and explain to others.



                        Now, when writing 0-based loops, they often have an invariant that relates a variable to how many items have been processed. E.g.



                        i = 0

                        #invariant: i contains the number of characters collected

                        while not endOfInput() and i < 10:

                        # invariant: i contains the number of characters collected

                        input[i] = getChar()

                        # (invariant temporarily broken)

                        i += 1

                        #invariant: i contains the number of characters collected

                        #invariant: i contains the number of characters collected


                        There are two basic ways to write the same loop with 1-based indexing:



                        i = 1
                        while not endOfInput() and i <= 10:
                        input[i] = getChar()
                        i += 1


                        In this case i does not represent the number of characters collected, so the invariant is a bit messier. (You would have to remember to subtract one later on if you wanted the count.) Here is the other way:



                        i = 0
                        while not endOfInput() and i < 10:
                        i += 1
                        input[i] = getChar()


                        Now the invariant holds again so this approach seems preferable, but it seems odd that the initial value of i can't be used as an array index—that we are not "ready to go" straight away and have to fix up i first. I suppose it's initially odd for learners of zero-based languages that, after the loop terminates, the variable is one more than the highest index used, but it all follows from the basic rule of "a list of size i can be indexed from 0 to i-1".



                        I admit that these arguments may not be very strong. That said, off-by-1 errors are one of the most common types of bug and at least in my experience, starting arrays from 1 needs a whole lot more adding and subtracting 1 than 0-based arrays.






                        share|improve this answer






















                        • +1 for the modulus operation argument. I also really like the nice invariants one. I always make a point of explaining to my team the importance of "least surprise" in designing and implementing new features (both in terms of UX design and code design). I feel the two concepts share commonality in that one of the aims of least surprise design is to preserve a high quantity of nice invariants!
                          – oliver-clare
                          2 days ago














                        up vote
                        4
                        down vote













                        From time to time I have had to do numerical work in MATLAB and the 1-based indexing always stuck out like a sore thumb, so I have a few examples I can provide where 0-based indexing is advantageous.



                        Modular access



                        This is the simplest example. If you want to "wrap around" an array, the modulus operator works like a charm. (And don't say "what if the modulus operator were defined from 1 to n instead"—that would be mathematically ludicrous.)



                        str = "This is the song that never ends... "
                        position = 300
                        charAtPosition = str[position % (str.length)]


                        Real world examples of this might include working with days of the week, generating repeating gradients, or coming up with a predicable item from a small list given a large ID number.



                        Discretisation



                        Let's say you want to generate a histogram of heights. The first "bucket" is 50cm-70cm. The next is 70-90cm. And so on up to 210cm.



                        Using zero-based indexing, the code looks like



                        bucket[floor((height - 50) / 20)] += 1


                        With 1-based indexing, it looks like



                        bucket[ceil((height - 50) / 20)] += 1
                        or
                        bucket[floor((height - 50) / 20) + 1] += 1


                        (the two have slightly different semantics). So you can either have a stray "+ 1" or use the ceil function. I believe the floor function is more "natural" than the ceil function since floor(a/b) is the quotient when you divide a by b; for this reason integer division often suffices in such calculations whereas the ceil version would be more complex. Also, if you wanted the buckets in reverse order, this is 0-based indexing:



                        BUCKETS = (210 - 50) / 20 - 1

                        #intuitive because BUCKETS - 1 is the highest index
                        bucket[(BUCKETS - 1) - floor((height - 50) / 20)] += 1


                        versus



                        #not intuitive... what does BUCKETS + 1 represent?
                        bucket[BUCKETS + 1 - ceil((height - 50) / 20)] += 1
                        or
                        #not intuitive... how come a forwards list needs "+ 1" but
                        #backwards list doesn't?
                        bucket[BUCKETS - floor((height - 50) / 20)] += 1


                        Change of Coordinate Systems



                        This is related to the above "direction flip". Although I will use a 1 dimensional example, this also applies to 2D and higher dimensional translations, rotations, and scaling.



                        Let's suppose, for each slot in the top row you want to find find the best fitting slot in the bottom row. (This often occurs when you want to efficiently reduce the quality of some data; image resizing is a 2D version of this).



                        With 0-based indexing:



                        0-based indexing



                        #intuitive because the centre of slot[0] is actually at x co-ordinate 0.5
                        nearest = floor((original + 0.5) / 5 * 7);


                        With 1-based indexing:



                        enter image description here



                        #Why -0.5? Can you explain? And then we need to "fix" it with a +1
                        nearest = floor((original - 0.5) / 5 * 7) + 1;


                        Nice Invariants



                        In order to prove that programs work correctly, computer scientists use the concept of an "invariant"—a property that is guaranteed to be true at a certain place in the code, no matter the program flow up to that point.



                        This is not just a theoretical concept. Even if invariants are not explicitly provided, code that has nice invariants tends to be easier to think about and explain to others.



                        Now, when writing 0-based loops, they often have an invariant that relates a variable to how many items have been processed. E.g.



                        i = 0

                        #invariant: i contains the number of characters collected

                        while not endOfInput() and i < 10:

                        # invariant: i contains the number of characters collected

                        input[i] = getChar()

                        # (invariant temporarily broken)

                        i += 1

                        #invariant: i contains the number of characters collected

                        #invariant: i contains the number of characters collected


                        There are two basic ways to write the same loop with 1-based indexing:



                        i = 1
                        while not endOfInput() and i <= 10:
                        input[i] = getChar()
                        i += 1


                        In this case i does not represent the number of characters collected, so the invariant is a bit messier. (You would have to remember to subtract one later on if you wanted the count.) Here is the other way:



                        i = 0
                        while not endOfInput() and i < 10:
                        i += 1
                        input[i] = getChar()


                        Now the invariant holds again so this approach seems preferable, but it seems odd that the initial value of i can't be used as an array index—that we are not "ready to go" straight away and have to fix up i first. I suppose it's initially odd for learners of zero-based languages that, after the loop terminates, the variable is one more than the highest index used, but it all follows from the basic rule of "a list of size i can be indexed from 0 to i-1".



                        I admit that these arguments may not be very strong. That said, off-by-1 errors are one of the most common types of bug and at least in my experience, starting arrays from 1 needs a whole lot more adding and subtracting 1 than 0-based arrays.






                        share|improve this answer






















                        • +1 for the modulus operation argument. I also really like the nice invariants one. I always make a point of explaining to my team the importance of "least surprise" in designing and implementing new features (both in terms of UX design and code design). I feel the two concepts share commonality in that one of the aims of least surprise design is to preserve a high quantity of nice invariants!
                          – oliver-clare
                          2 days ago












                        up vote
                        4
                        down vote










                        up vote
                        4
                        down vote









                        From time to time I have had to do numerical work in MATLAB and the 1-based indexing always stuck out like a sore thumb, so I have a few examples I can provide where 0-based indexing is advantageous.



                        Modular access



                        This is the simplest example. If you want to "wrap around" an array, the modulus operator works like a charm. (And don't say "what if the modulus operator were defined from 1 to n instead"—that would be mathematically ludicrous.)



                        str = "This is the song that never ends... "
                        position = 300
                        charAtPosition = str[position % (str.length)]


                        Real world examples of this might include working with days of the week, generating repeating gradients, or coming up with a predicable item from a small list given a large ID number.



                        Discretisation



                        Let's say you want to generate a histogram of heights. The first "bucket" is 50cm-70cm. The next is 70-90cm. And so on up to 210cm.



                        Using zero-based indexing, the code looks like



                        bucket[floor((height - 50) / 20)] += 1


                        With 1-based indexing, it looks like



                        bucket[ceil((height - 50) / 20)] += 1
                        or
                        bucket[floor((height - 50) / 20) + 1] += 1


                        (the two have slightly different semantics). So you can either have a stray "+ 1" or use the ceil function. I believe the floor function is more "natural" than the ceil function since floor(a/b) is the quotient when you divide a by b; for this reason integer division often suffices in such calculations whereas the ceil version would be more complex. Also, if you wanted the buckets in reverse order, this is 0-based indexing:



                        BUCKETS = (210 - 50) / 20 - 1

                        #intuitive because BUCKETS - 1 is the highest index
                        bucket[(BUCKETS - 1) - floor((height - 50) / 20)] += 1


                        versus



                        #not intuitive... what does BUCKETS + 1 represent?
                        bucket[BUCKETS + 1 - ceil((height - 50) / 20)] += 1
                        or
                        #not intuitive... how come a forwards list needs "+ 1" but
                        #backwards list doesn't?
                        bucket[BUCKETS - floor((height - 50) / 20)] += 1


                        Change of Coordinate Systems



                        This is related to the above "direction flip". Although I will use a 1 dimensional example, this also applies to 2D and higher dimensional translations, rotations, and scaling.



                        Let's suppose, for each slot in the top row you want to find find the best fitting slot in the bottom row. (This often occurs when you want to efficiently reduce the quality of some data; image resizing is a 2D version of this).



                        With 0-based indexing:



                        0-based indexing



                        #intuitive because the centre of slot[0] is actually at x co-ordinate 0.5
                        nearest = floor((original + 0.5) / 5 * 7);


                        With 1-based indexing:



                        enter image description here



                        #Why -0.5? Can you explain? And then we need to "fix" it with a +1
                        nearest = floor((original - 0.5) / 5 * 7) + 1;


                        Nice Invariants



                        In order to prove that programs work correctly, computer scientists use the concept of an "invariant"—a property that is guaranteed to be true at a certain place in the code, no matter the program flow up to that point.



                        This is not just a theoretical concept. Even if invariants are not explicitly provided, code that has nice invariants tends to be easier to think about and explain to others.



                        Now, when writing 0-based loops, they often have an invariant that relates a variable to how many items have been processed. E.g.



                        i = 0

                        #invariant: i contains the number of characters collected

                        while not endOfInput() and i < 10:

                        # invariant: i contains the number of characters collected

                        input[i] = getChar()

                        # (invariant temporarily broken)

                        i += 1

                        #invariant: i contains the number of characters collected

                        #invariant: i contains the number of characters collected


                        There are two basic ways to write the same loop with 1-based indexing:



                        i = 1
                        while not endOfInput() and i <= 10:
                        input[i] = getChar()
                        i += 1


                        In this case i does not represent the number of characters collected, so the invariant is a bit messier. (You would have to remember to subtract one later on if you wanted the count.) Here is the other way:



                        i = 0
                        while not endOfInput() and i < 10:
                        i += 1
                        input[i] = getChar()


                        Now the invariant holds again so this approach seems preferable, but it seems odd that the initial value of i can't be used as an array index—that we are not "ready to go" straight away and have to fix up i first. I suppose it's initially odd for learners of zero-based languages that, after the loop terminates, the variable is one more than the highest index used, but it all follows from the basic rule of "a list of size i can be indexed from 0 to i-1".



                        I admit that these arguments may not be very strong. That said, off-by-1 errors are one of the most common types of bug and at least in my experience, starting arrays from 1 needs a whole lot more adding and subtracting 1 than 0-based arrays.






                        share|improve this answer














                        From time to time I have had to do numerical work in MATLAB and the 1-based indexing always stuck out like a sore thumb, so I have a few examples I can provide where 0-based indexing is advantageous.



                        Modular access



                        This is the simplest example. If you want to "wrap around" an array, the modulus operator works like a charm. (And don't say "what if the modulus operator were defined from 1 to n instead"—that would be mathematically ludicrous.)



                        str = "This is the song that never ends... "
                        position = 300
                        charAtPosition = str[position % (str.length)]


                        Real world examples of this might include working with days of the week, generating repeating gradients, or coming up with a predicable item from a small list given a large ID number.



                        Discretisation



                        Let's say you want to generate a histogram of heights. The first "bucket" is 50cm-70cm. The next is 70-90cm. And so on up to 210cm.



                        Using zero-based indexing, the code looks like



                        bucket[floor((height - 50) / 20)] += 1


                        With 1-based indexing, it looks like



                        bucket[ceil((height - 50) / 20)] += 1
                        or
                        bucket[floor((height - 50) / 20) + 1] += 1


                        (the two have slightly different semantics). So you can either have a stray "+ 1" or use the ceil function. I believe the floor function is more "natural" than the ceil function since floor(a/b) is the quotient when you divide a by b; for this reason integer division often suffices in such calculations whereas the ceil version would be more complex. Also, if you wanted the buckets in reverse order, this is 0-based indexing:



                        BUCKETS = (210 - 50) / 20 - 1

                        #intuitive because BUCKETS - 1 is the highest index
                        bucket[(BUCKETS - 1) - floor((height - 50) / 20)] += 1


                        versus



                        #not intuitive... what does BUCKETS + 1 represent?
                        bucket[BUCKETS + 1 - ceil((height - 50) / 20)] += 1
                        or
                        #not intuitive... how come a forwards list needs "+ 1" but
                        #backwards list doesn't?
                        bucket[BUCKETS - floor((height - 50) / 20)] += 1


                        Change of Coordinate Systems



                        This is related to the above "direction flip". Although I will use a 1 dimensional example, this also applies to 2D and higher dimensional translations, rotations, and scaling.



                        Let's suppose, for each slot in the top row you want to find find the best fitting slot in the bottom row. (This often occurs when you want to efficiently reduce the quality of some data; image resizing is a 2D version of this).



                        With 0-based indexing:



                        0-based indexing



                        #intuitive because the centre of slot[0] is actually at x co-ordinate 0.5
                        nearest = floor((original + 0.5) / 5 * 7);


                        With 1-based indexing:



                        enter image description here



                        #Why -0.5? Can you explain? And then we need to "fix" it with a +1
                        nearest = floor((original - 0.5) / 5 * 7) + 1;


                        Nice Invariants



                        In order to prove that programs work correctly, computer scientists use the concept of an "invariant"—a property that is guaranteed to be true at a certain place in the code, no matter the program flow up to that point.



                        This is not just a theoretical concept. Even if invariants are not explicitly provided, code that has nice invariants tends to be easier to think about and explain to others.



                        Now, when writing 0-based loops, they often have an invariant that relates a variable to how many items have been processed. E.g.



                        i = 0

                        #invariant: i contains the number of characters collected

                        while not endOfInput() and i < 10:

                        # invariant: i contains the number of characters collected

                        input[i] = getChar()

                        # (invariant temporarily broken)

                        i += 1

                        #invariant: i contains the number of characters collected

                        #invariant: i contains the number of characters collected


                        There are two basic ways to write the same loop with 1-based indexing:



                        i = 1
                        while not endOfInput() and i <= 10:
                        input[i] = getChar()
                        i += 1


                        In this case i does not represent the number of characters collected, so the invariant is a bit messier. (You would have to remember to subtract one later on if you wanted the count.) Here is the other way:



                        i = 0
                        while not endOfInput() and i < 10:
                        i += 1
                        input[i] = getChar()


                        Now the invariant holds again so this approach seems preferable, but it seems odd that the initial value of i can't be used as an array index—that we are not "ready to go" straight away and have to fix up i first. I suppose it's initially odd for learners of zero-based languages that, after the loop terminates, the variable is one more than the highest index used, but it all follows from the basic rule of "a list of size i can be indexed from 0 to i-1".



                        I admit that these arguments may not be very strong. That said, off-by-1 errors are one of the most common types of bug and at least in my experience, starting arrays from 1 needs a whole lot more adding and subtracting 1 than 0-based arrays.







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Sep 7 at 11:01

























                        answered Sep 7 at 10:52









                        Artelius

                        1913




                        1913











                        • +1 for the modulus operation argument. I also really like the nice invariants one. I always make a point of explaining to my team the importance of "least surprise" in designing and implementing new features (both in terms of UX design and code design). I feel the two concepts share commonality in that one of the aims of least surprise design is to preserve a high quantity of nice invariants!
                          – oliver-clare
                          2 days ago
















                        • +1 for the modulus operation argument. I also really like the nice invariants one. I always make a point of explaining to my team the importance of "least surprise" in designing and implementing new features (both in terms of UX design and code design). I feel the two concepts share commonality in that one of the aims of least surprise design is to preserve a high quantity of nice invariants!
                          – oliver-clare
                          2 days ago















                        +1 for the modulus operation argument. I also really like the nice invariants one. I always make a point of explaining to my team the importance of "least surprise" in designing and implementing new features (both in terms of UX design and code design). I feel the two concepts share commonality in that one of the aims of least surprise design is to preserve a high quantity of nice invariants!
                        – oliver-clare
                        2 days ago




                        +1 for the modulus operation argument. I also really like the nice invariants one. I always make a point of explaining to my team the importance of "least surprise" in designing and implementing new features (both in terms of UX design and code design). I feel the two concepts share commonality in that one of the aims of least surprise design is to preserve a high quantity of nice invariants!
                        – oliver-clare
                        2 days ago










                        up vote
                        2
                        down vote













                        I think that one of the first programming languages to use zero-based indexing was BCPL. In BCPL, pointers and integers are interchangable, and arrays are represented by pointers. Subscripting uses the operator !, so you can get the first and second members of an array using A!0 or A!1. These are defined to be equivalent to !(A+0) and !(A+1) where the unary ! operator dereferences a pointer. It's neat, simple, and consistent, and it wouldn't work with 1-based addressing.



                        A lot of BCPL ideas were carried into C, and the rest is history.



                        But although zero-based indexing seems to work best for system programming languages, there are many modern languages that chose to start at 1. XPath is an obvious example. I think the rationale there was that it was expected to be used by non-programmers (e.g document authors) and you can't expect a document author to think of the first chapter in a book as chapter 0.






                        share|improve this answer




















                        • Indeed BCPL seems to be origin of 0-based indexing. We can try to explain to ourselves or to pupils why indexing starts from 0, but the fact is that it only does so in certain languages, and that most of those do so out of historical reasons. This blog shines some light on the origin of 0-indexing: exple.tive.org/blarg/2013/10/22/citation-needed
                          – idrougge
                          Sep 6 at 12:37











                        • Nice blog article. I'm amused by the notion that we're more likely to have heard of Eben Upton than of Martin Richards.
                          – Michael Kay
                          Sep 6 at 13:31










                        • ... It reflects that the author is clearly digging into software history for the first time and is suprised by his discoveries, thinking that perhaps no-one else knows this. However, his conclusions are a bit inconsistent. Zero based indexing in BCPL was an inevitable consequence of having pointers rather than arrays as the fundamental data structuring concept, it wasn't to make array indexing more efficient.
                          – Michael Kay
                          Sep 6 at 13:38










                        • Since we're on Computer Science Educators, I might mention that Martin Richards and Steve Bourne between them probably taught me everything I really needed to know about programming -- mainly by example; they both wrote beautiful code.
                          – Michael Kay
                          Sep 6 at 13:42














                        up vote
                        2
                        down vote













                        I think that one of the first programming languages to use zero-based indexing was BCPL. In BCPL, pointers and integers are interchangable, and arrays are represented by pointers. Subscripting uses the operator !, so you can get the first and second members of an array using A!0 or A!1. These are defined to be equivalent to !(A+0) and !(A+1) where the unary ! operator dereferences a pointer. It's neat, simple, and consistent, and it wouldn't work with 1-based addressing.



                        A lot of BCPL ideas were carried into C, and the rest is history.



                        But although zero-based indexing seems to work best for system programming languages, there are many modern languages that chose to start at 1. XPath is an obvious example. I think the rationale there was that it was expected to be used by non-programmers (e.g document authors) and you can't expect a document author to think of the first chapter in a book as chapter 0.






                        share|improve this answer




















                        • Indeed BCPL seems to be origin of 0-based indexing. We can try to explain to ourselves or to pupils why indexing starts from 0, but the fact is that it only does so in certain languages, and that most of those do so out of historical reasons. This blog shines some light on the origin of 0-indexing: exple.tive.org/blarg/2013/10/22/citation-needed
                          – idrougge
                          Sep 6 at 12:37











                        • Nice blog article. I'm amused by the notion that we're more likely to have heard of Eben Upton than of Martin Richards.
                          – Michael Kay
                          Sep 6 at 13:31










                        • ... It reflects that the author is clearly digging into software history for the first time and is suprised by his discoveries, thinking that perhaps no-one else knows this. However, his conclusions are a bit inconsistent. Zero based indexing in BCPL was an inevitable consequence of having pointers rather than arrays as the fundamental data structuring concept, it wasn't to make array indexing more efficient.
                          – Michael Kay
                          Sep 6 at 13:38










                        • Since we're on Computer Science Educators, I might mention that Martin Richards and Steve Bourne between them probably taught me everything I really needed to know about programming -- mainly by example; they both wrote beautiful code.
                          – Michael Kay
                          Sep 6 at 13:42












                        up vote
                        2
                        down vote










                        up vote
                        2
                        down vote









                        I think that one of the first programming languages to use zero-based indexing was BCPL. In BCPL, pointers and integers are interchangable, and arrays are represented by pointers. Subscripting uses the operator !, so you can get the first and second members of an array using A!0 or A!1. These are defined to be equivalent to !(A+0) and !(A+1) where the unary ! operator dereferences a pointer. It's neat, simple, and consistent, and it wouldn't work with 1-based addressing.



                        A lot of BCPL ideas were carried into C, and the rest is history.



                        But although zero-based indexing seems to work best for system programming languages, there are many modern languages that chose to start at 1. XPath is an obvious example. I think the rationale there was that it was expected to be used by non-programmers (e.g document authors) and you can't expect a document author to think of the first chapter in a book as chapter 0.






                        share|improve this answer












                        I think that one of the first programming languages to use zero-based indexing was BCPL. In BCPL, pointers and integers are interchangable, and arrays are represented by pointers. Subscripting uses the operator !, so you can get the first and second members of an array using A!0 or A!1. These are defined to be equivalent to !(A+0) and !(A+1) where the unary ! operator dereferences a pointer. It's neat, simple, and consistent, and it wouldn't work with 1-based addressing.



                        A lot of BCPL ideas were carried into C, and the rest is history.



                        But although zero-based indexing seems to work best for system programming languages, there are many modern languages that chose to start at 1. XPath is an obvious example. I think the rationale there was that it was expected to be used by non-programmers (e.g document authors) and you can't expect a document author to think of the first chapter in a book as chapter 0.







                        share|improve this answer












                        share|improve this answer



                        share|improve this answer










                        answered Sep 3 at 10:20









                        Michael Kay

                        31613




                        31613











                        • Indeed BCPL seems to be origin of 0-based indexing. We can try to explain to ourselves or to pupils why indexing starts from 0, but the fact is that it only does so in certain languages, and that most of those do so out of historical reasons. This blog shines some light on the origin of 0-indexing: exple.tive.org/blarg/2013/10/22/citation-needed
                          – idrougge
                          Sep 6 at 12:37











                        • Nice blog article. I'm amused by the notion that we're more likely to have heard of Eben Upton than of Martin Richards.
                          – Michael Kay
                          Sep 6 at 13:31










                        • ... It reflects that the author is clearly digging into software history for the first time and is suprised by his discoveries, thinking that perhaps no-one else knows this. However, his conclusions are a bit inconsistent. Zero based indexing in BCPL was an inevitable consequence of having pointers rather than arrays as the fundamental data structuring concept, it wasn't to make array indexing more efficient.
                          – Michael Kay
                          Sep 6 at 13:38










                        • Since we're on Computer Science Educators, I might mention that Martin Richards and Steve Bourne between them probably taught me everything I really needed to know about programming -- mainly by example; they both wrote beautiful code.
                          – Michael Kay
                          Sep 6 at 13:42
















                        • Indeed BCPL seems to be origin of 0-based indexing. We can try to explain to ourselves or to pupils why indexing starts from 0, but the fact is that it only does so in certain languages, and that most of those do so out of historical reasons. This blog shines some light on the origin of 0-indexing: exple.tive.org/blarg/2013/10/22/citation-needed
                          – idrougge
                          Sep 6 at 12:37











                        • Nice blog article. I'm amused by the notion that we're more likely to have heard of Eben Upton than of Martin Richards.
                          – Michael Kay
                          Sep 6 at 13:31










                        • ... It reflects that the author is clearly digging into software history for the first time and is suprised by his discoveries, thinking that perhaps no-one else knows this. However, his conclusions are a bit inconsistent. Zero based indexing in BCPL was an inevitable consequence of having pointers rather than arrays as the fundamental data structuring concept, it wasn't to make array indexing more efficient.
                          – Michael Kay
                          Sep 6 at 13:38










                        • Since we're on Computer Science Educators, I might mention that Martin Richards and Steve Bourne between them probably taught me everything I really needed to know about programming -- mainly by example; they both wrote beautiful code.
                          – Michael Kay
                          Sep 6 at 13:42















                        Indeed BCPL seems to be origin of 0-based indexing. We can try to explain to ourselves or to pupils why indexing starts from 0, but the fact is that it only does so in certain languages, and that most of those do so out of historical reasons. This blog shines some light on the origin of 0-indexing: exple.tive.org/blarg/2013/10/22/citation-needed
                        – idrougge
                        Sep 6 at 12:37





                        Indeed BCPL seems to be origin of 0-based indexing. We can try to explain to ourselves or to pupils why indexing starts from 0, but the fact is that it only does so in certain languages, and that most of those do so out of historical reasons. This blog shines some light on the origin of 0-indexing: exple.tive.org/blarg/2013/10/22/citation-needed
                        – idrougge
                        Sep 6 at 12:37













                        Nice blog article. I'm amused by the notion that we're more likely to have heard of Eben Upton than of Martin Richards.
                        – Michael Kay
                        Sep 6 at 13:31




                        Nice blog article. I'm amused by the notion that we're more likely to have heard of Eben Upton than of Martin Richards.
                        – Michael Kay
                        Sep 6 at 13:31












                        ... It reflects that the author is clearly digging into software history for the first time and is suprised by his discoveries, thinking that perhaps no-one else knows this. However, his conclusions are a bit inconsistent. Zero based indexing in BCPL was an inevitable consequence of having pointers rather than arrays as the fundamental data structuring concept, it wasn't to make array indexing more efficient.
                        – Michael Kay
                        Sep 6 at 13:38




                        ... It reflects that the author is clearly digging into software history for the first time and is suprised by his discoveries, thinking that perhaps no-one else knows this. However, his conclusions are a bit inconsistent. Zero based indexing in BCPL was an inevitable consequence of having pointers rather than arrays as the fundamental data structuring concept, it wasn't to make array indexing more efficient.
                        – Michael Kay
                        Sep 6 at 13:38












                        Since we're on Computer Science Educators, I might mention that Martin Richards and Steve Bourne between them probably taught me everything I really needed to know about programming -- mainly by example; they both wrote beautiful code.
                        – Michael Kay
                        Sep 6 at 13:42




                        Since we're on Computer Science Educators, I might mention that Martin Richards and Steve Bourne between them probably taught me everything I really needed to know about programming -- mainly by example; they both wrote beautiful code.
                        – Michael Kay
                        Sep 6 at 13:42










                        up vote
                        2
                        down vote













                        Slight generalization of CJ Denis's answer: The advantage of zero-based indexing is apparent as soon as you start working with relative indices. If you have a base array A and over it, let's say, a sliding window W, you would have to subtract 1 each time you add W-based index to the A-based one.






                        share|improve this answer
























                          up vote
                          2
                          down vote













                          Slight generalization of CJ Denis's answer: The advantage of zero-based indexing is apparent as soon as you start working with relative indices. If you have a base array A and over it, let's say, a sliding window W, you would have to subtract 1 each time you add W-based index to the A-based one.






                          share|improve this answer






















                            up vote
                            2
                            down vote










                            up vote
                            2
                            down vote









                            Slight generalization of CJ Denis's answer: The advantage of zero-based indexing is apparent as soon as you start working with relative indices. If you have a base array A and over it, let's say, a sliding window W, you would have to subtract 1 each time you add W-based index to the A-based one.






                            share|improve this answer












                            Slight generalization of CJ Denis's answer: The advantage of zero-based indexing is apparent as soon as you start working with relative indices. If you have a base array A and over it, let's say, a sliding window W, you would have to subtract 1 each time you add W-based index to the A-based one.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Sep 3 at 12:00









                            Edheldil

                            211




                            211




















                                up vote
                                2
                                down vote













                                Why not?



                                Why not count from zero? (This answer is a bit like Buffy's answer, but a bit simpler logic than many of the other answers.) Zero is a perfectly valid number. So why not use it? Failing to use that available number is just a waste of the possibility of using that number. You wouldn't want to start lower, since negative numbers may be a bit more complicated to need to consider, and may even be unavailable (when using unsigned numbers). But zero is available, so why waste the possibility of being able to use that number?



                                If you do that, it's like the 63 SPT (sectors per track/head) limit that contributed to the 504 MiB / 528 MB) Barrier. That used a 1-based count. If a zero-based count were used, a limit would have been 512 MB instead of 504 MB. In a day and age when hard drives were counted in megabytes, that limit was nearly 1.6% smaller because someone decided to do a one-based count for one of the numbers. So, keeping that real-world actual cost in mind, what benefit is there to trying to exclude zero? If there isn't one, then don't do it.



                                Standardizing on one number is nice. When I was ten years old, I knew how to program. Sometimes I counted from one (e.g., "for(x=1;x<=10;x++)" ), while other times I counted from zero (e.g., "for(x=0;x<10;x++)" ). Sometimes I would mix up those methods, and create a fencepost bug (using "for(x=0;x<=10;x++)" ). Later in life, I was pretty strongly compelled to count from zero and drop the test for equality (just testing for inequality using <, instead of "less-than-or-equal" using <=), and once I got into a standardized habit, I found myself to be far less likely to be making those off-by-one errors.



                                Ultimately, the code of in many "high level" programming languages is just meant to be converted into "low level" assembly language, which is designed to operate the same way as an actual chip. Zero is kind of a special number (having unique properties with addition and multiplication), while one has less special behavior (having a similar unique property with multiplication, but not addition). So it makes a bit of sense for zero to be special.



                                Also, if you think of the "what's left", zero is more logical. If you count down ("'for x=10;x;x--)`"), then do you want to exit when there is one job left, or zero jobs left? Zero is more sensible in that particular case, and that may be a key reason why some of the Intel Assembly Language operators perform the way they do.






                                share|improve this answer
























                                  up vote
                                  2
                                  down vote













                                  Why not?



                                  Why not count from zero? (This answer is a bit like Buffy's answer, but a bit simpler logic than many of the other answers.) Zero is a perfectly valid number. So why not use it? Failing to use that available number is just a waste of the possibility of using that number. You wouldn't want to start lower, since negative numbers may be a bit more complicated to need to consider, and may even be unavailable (when using unsigned numbers). But zero is available, so why waste the possibility of being able to use that number?



                                  If you do that, it's like the 63 SPT (sectors per track/head) limit that contributed to the 504 MiB / 528 MB) Barrier. That used a 1-based count. If a zero-based count were used, a limit would have been 512 MB instead of 504 MB. In a day and age when hard drives were counted in megabytes, that limit was nearly 1.6% smaller because someone decided to do a one-based count for one of the numbers. So, keeping that real-world actual cost in mind, what benefit is there to trying to exclude zero? If there isn't one, then don't do it.



                                  Standardizing on one number is nice. When I was ten years old, I knew how to program. Sometimes I counted from one (e.g., "for(x=1;x<=10;x++)" ), while other times I counted from zero (e.g., "for(x=0;x<10;x++)" ). Sometimes I would mix up those methods, and create a fencepost bug (using "for(x=0;x<=10;x++)" ). Later in life, I was pretty strongly compelled to count from zero and drop the test for equality (just testing for inequality using <, instead of "less-than-or-equal" using <=), and once I got into a standardized habit, I found myself to be far less likely to be making those off-by-one errors.



                                  Ultimately, the code of in many "high level" programming languages is just meant to be converted into "low level" assembly language, which is designed to operate the same way as an actual chip. Zero is kind of a special number (having unique properties with addition and multiplication), while one has less special behavior (having a similar unique property with multiplication, but not addition). So it makes a bit of sense for zero to be special.



                                  Also, if you think of the "what's left", zero is more logical. If you count down ("'for x=10;x;x--)`"), then do you want to exit when there is one job left, or zero jobs left? Zero is more sensible in that particular case, and that may be a key reason why some of the Intel Assembly Language operators perform the way they do.






                                  share|improve this answer






















                                    up vote
                                    2
                                    down vote










                                    up vote
                                    2
                                    down vote









                                    Why not?



                                    Why not count from zero? (This answer is a bit like Buffy's answer, but a bit simpler logic than many of the other answers.) Zero is a perfectly valid number. So why not use it? Failing to use that available number is just a waste of the possibility of using that number. You wouldn't want to start lower, since negative numbers may be a bit more complicated to need to consider, and may even be unavailable (when using unsigned numbers). But zero is available, so why waste the possibility of being able to use that number?



                                    If you do that, it's like the 63 SPT (sectors per track/head) limit that contributed to the 504 MiB / 528 MB) Barrier. That used a 1-based count. If a zero-based count were used, a limit would have been 512 MB instead of 504 MB. In a day and age when hard drives were counted in megabytes, that limit was nearly 1.6% smaller because someone decided to do a one-based count for one of the numbers. So, keeping that real-world actual cost in mind, what benefit is there to trying to exclude zero? If there isn't one, then don't do it.



                                    Standardizing on one number is nice. When I was ten years old, I knew how to program. Sometimes I counted from one (e.g., "for(x=1;x<=10;x++)" ), while other times I counted from zero (e.g., "for(x=0;x<10;x++)" ). Sometimes I would mix up those methods, and create a fencepost bug (using "for(x=0;x<=10;x++)" ). Later in life, I was pretty strongly compelled to count from zero and drop the test for equality (just testing for inequality using <, instead of "less-than-or-equal" using <=), and once I got into a standardized habit, I found myself to be far less likely to be making those off-by-one errors.



                                    Ultimately, the code of in many "high level" programming languages is just meant to be converted into "low level" assembly language, which is designed to operate the same way as an actual chip. Zero is kind of a special number (having unique properties with addition and multiplication), while one has less special behavior (having a similar unique property with multiplication, but not addition). So it makes a bit of sense for zero to be special.



                                    Also, if you think of the "what's left", zero is more logical. If you count down ("'for x=10;x;x--)`"), then do you want to exit when there is one job left, or zero jobs left? Zero is more sensible in that particular case, and that may be a key reason why some of the Intel Assembly Language operators perform the way they do.






                                    share|improve this answer












                                    Why not?



                                    Why not count from zero? (This answer is a bit like Buffy's answer, but a bit simpler logic than many of the other answers.) Zero is a perfectly valid number. So why not use it? Failing to use that available number is just a waste of the possibility of using that number. You wouldn't want to start lower, since negative numbers may be a bit more complicated to need to consider, and may even be unavailable (when using unsigned numbers). But zero is available, so why waste the possibility of being able to use that number?



                                    If you do that, it's like the 63 SPT (sectors per track/head) limit that contributed to the 504 MiB / 528 MB) Barrier. That used a 1-based count. If a zero-based count were used, a limit would have been 512 MB instead of 504 MB. In a day and age when hard drives were counted in megabytes, that limit was nearly 1.6% smaller because someone decided to do a one-based count for one of the numbers. So, keeping that real-world actual cost in mind, what benefit is there to trying to exclude zero? If there isn't one, then don't do it.



                                    Standardizing on one number is nice. When I was ten years old, I knew how to program. Sometimes I counted from one (e.g., "for(x=1;x<=10;x++)" ), while other times I counted from zero (e.g., "for(x=0;x<10;x++)" ). Sometimes I would mix up those methods, and create a fencepost bug (using "for(x=0;x<=10;x++)" ). Later in life, I was pretty strongly compelled to count from zero and drop the test for equality (just testing for inequality using <, instead of "less-than-or-equal" using <=), and once I got into a standardized habit, I found myself to be far less likely to be making those off-by-one errors.



                                    Ultimately, the code of in many "high level" programming languages is just meant to be converted into "low level" assembly language, which is designed to operate the same way as an actual chip. Zero is kind of a special number (having unique properties with addition and multiplication), while one has less special behavior (having a similar unique property with multiplication, but not addition). So it makes a bit of sense for zero to be special.



                                    Also, if you think of the "what's left", zero is more logical. If you count down ("'for x=10;x;x--)`"), then do you want to exit when there is one job left, or zero jobs left? Zero is more sensible in that particular case, and that may be a key reason why some of the Intel Assembly Language operators perform the way they do.







                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Sep 7 at 4:07









                                    TOOGAM

                                    22113




                                    22113




















                                        up vote
                                        1
                                        down vote













                                        I think it's best to view addresses and indices not as identifying objects or elements, but rather the spaces between or on either side of them. Thus, an array with four elements would have the following indices:



                                        Addr: Base+0 Base+1 Base+2 Base+3 Base+4
                                        . V V V V V
                                        Indices: 0 1 2 3 4
                                        Elements [FIRST] [SECOND] [THIRD] [FOURTH]


                                        Each element is associated with two addresses--the one immediately preceding it and the one immediately following it. The address immediately following any element other than the last will immediately precede another element, and likewise the address immediately preceding any element other than the first will follow another element. Even though each address other than the first and last will be associated with two elements (one preceding and one following), by convention applying the * operator to an address yields the one following.



                                        Note that unlike the "half-open interval" view, this approach does not require any special handling for pointers that go one beyond the last element. The address "Base+4" above is associated with the four-element array just like any other, but the * operator cannot be applied to it because that operator would require the ability to compute the next address.






                                        share|improve this answer




















                                        • I like this. This is also a useful way of thinking about labels in assembly language (as zero-width). Addresses and labels don't have any natural width associated with them; that depends on what type of load/store you do. (The type system in most languages associates an element width with a pointer, but this is why you can't add/subtract void* in C.)
                                          – Peter Cordes
                                          Sep 5 at 1:54















                                        up vote
                                        1
                                        down vote













                                        I think it's best to view addresses and indices not as identifying objects or elements, but rather the spaces between or on either side of them. Thus, an array with four elements would have the following indices:



                                        Addr: Base+0 Base+1 Base+2 Base+3 Base+4
                                        . V V V V V
                                        Indices: 0 1 2 3 4
                                        Elements [FIRST] [SECOND] [THIRD] [FOURTH]


                                        Each element is associated with two addresses--the one immediately preceding it and the one immediately following it. The address immediately following any element other than the last will immediately precede another element, and likewise the address immediately preceding any element other than the first will follow another element. Even though each address other than the first and last will be associated with two elements (one preceding and one following), by convention applying the * operator to an address yields the one following.



                                        Note that unlike the "half-open interval" view, this approach does not require any special handling for pointers that go one beyond the last element. The address "Base+4" above is associated with the four-element array just like any other, but the * operator cannot be applied to it because that operator would require the ability to compute the next address.






                                        share|improve this answer




















                                        • I like this. This is also a useful way of thinking about labels in assembly language (as zero-width). Addresses and labels don't have any natural width associated with them; that depends on what type of load/store you do. (The type system in most languages associates an element width with a pointer, but this is why you can't add/subtract void* in C.)
                                          – Peter Cordes
                                          Sep 5 at 1:54













                                        up vote
                                        1
                                        down vote










                                        up vote
                                        1
                                        down vote









                                        I think it's best to view addresses and indices not as identifying objects or elements, but rather the spaces between or on either side of them. Thus, an array with four elements would have the following indices:



                                        Addr: Base+0 Base+1 Base+2 Base+3 Base+4
                                        . V V V V V
                                        Indices: 0 1 2 3 4
                                        Elements [FIRST] [SECOND] [THIRD] [FOURTH]


                                        Each element is associated with two addresses--the one immediately preceding it and the one immediately following it. The address immediately following any element other than the last will immediately precede another element, and likewise the address immediately preceding any element other than the first will follow another element. Even though each address other than the first and last will be associated with two elements (one preceding and one following), by convention applying the * operator to an address yields the one following.



                                        Note that unlike the "half-open interval" view, this approach does not require any special handling for pointers that go one beyond the last element. The address "Base+4" above is associated with the four-element array just like any other, but the * operator cannot be applied to it because that operator would require the ability to compute the next address.






                                        share|improve this answer












                                        I think it's best to view addresses and indices not as identifying objects or elements, but rather the spaces between or on either side of them. Thus, an array with four elements would have the following indices:



                                        Addr: Base+0 Base+1 Base+2 Base+3 Base+4
                                        . V V V V V
                                        Indices: 0 1 2 3 4
                                        Elements [FIRST] [SECOND] [THIRD] [FOURTH]


                                        Each element is associated with two addresses--the one immediately preceding it and the one immediately following it. The address immediately following any element other than the last will immediately precede another element, and likewise the address immediately preceding any element other than the first will follow another element. Even though each address other than the first and last will be associated with two elements (one preceding and one following), by convention applying the * operator to an address yields the one following.



                                        Note that unlike the "half-open interval" view, this approach does not require any special handling for pointers that go one beyond the last element. The address "Base+4" above is associated with the four-element array just like any other, but the * operator cannot be applied to it because that operator would require the ability to compute the next address.







                                        share|improve this answer












                                        share|improve this answer



                                        share|improve this answer










                                        answered Sep 4 at 19:31









                                        supercat

                                        1294




                                        1294











                                        • I like this. This is also a useful way of thinking about labels in assembly language (as zero-width). Addresses and labels don't have any natural width associated with them; that depends on what type of load/store you do. (The type system in most languages associates an element width with a pointer, but this is why you can't add/subtract void* in C.)
                                          – Peter Cordes
                                          Sep 5 at 1:54

















                                        • I like this. This is also a useful way of thinking about labels in assembly language (as zero-width). Addresses and labels don't have any natural width associated with them; that depends on what type of load/store you do. (The type system in most languages associates an element width with a pointer, but this is why you can't add/subtract void* in C.)
                                          – Peter Cordes
                                          Sep 5 at 1:54
















                                        I like this. This is also a useful way of thinking about labels in assembly language (as zero-width). Addresses and labels don't have any natural width associated with them; that depends on what type of load/store you do. (The type system in most languages associates an element width with a pointer, but this is why you can't add/subtract void* in C.)
                                        – Peter Cordes
                                        Sep 5 at 1:54





                                        I like this. This is also a useful way of thinking about labels in assembly language (as zero-width). Addresses and labels don't have any natural width associated with them; that depends on what type of load/store you do. (The type system in most languages associates an element width with a pointer, but this is why you can't add/subtract void* in C.)
                                        – Peter Cordes
                                        Sep 5 at 1:54











                                        up vote
                                        1
                                        down vote













                                        There are many answers but I miss an attempt to make it short and comprehensible for non programmers.




                                        I don't really want to be explaining memory addresses to a new programmer who doesn't understand memory layout and maybe doesn't even understand arrays yet.




                                        A simple and short example.

                                        We have a list of elements aligned one after the other. The start of this list, the first element is flagged with a pin.

                                        To get the first element, we go to where the pin is.

                                        To get the second element, we need to go to the pin plus one element.

                                        Starting at zero the computer can simply calculate where to go from the start location.



                                        More thoughts on that.

                                        Counting starts with "one" for the first element. Even for programmers. But programmers don't count elements when they start at zero, they give them names. These names start at the first number that can be built with digits. Zero denotes "nothing" but is the first valid number.




                                        couldn't a modern compiler often optimize this away?




                                        I think it can't. How? The calculation described above is fundamental, the CPU does it like that. A compiler can't optimize necessary calculations away.






                                        share|improve this answer








                                        New contributor




                                        puck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                        Check out our Code of Conduct.





















                                          up vote
                                          1
                                          down vote













                                          There are many answers but I miss an attempt to make it short and comprehensible for non programmers.




                                          I don't really want to be explaining memory addresses to a new programmer who doesn't understand memory layout and maybe doesn't even understand arrays yet.




                                          A simple and short example.

                                          We have a list of elements aligned one after the other. The start of this list, the first element is flagged with a pin.

                                          To get the first element, we go to where the pin is.

                                          To get the second element, we need to go to the pin plus one element.

                                          Starting at zero the computer can simply calculate where to go from the start location.



                                          More thoughts on that.

                                          Counting starts with "one" for the first element. Even for programmers. But programmers don't count elements when they start at zero, they give them names. These names start at the first number that can be built with digits. Zero denotes "nothing" but is the first valid number.




                                          couldn't a modern compiler often optimize this away?




                                          I think it can't. How? The calculation described above is fundamental, the CPU does it like that. A compiler can't optimize necessary calculations away.






                                          share|improve this answer








                                          New contributor




                                          puck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                          Check out our Code of Conduct.



















                                            up vote
                                            1
                                            down vote










                                            up vote
                                            1
                                            down vote









                                            There are many answers but I miss an attempt to make it short and comprehensible for non programmers.




                                            I don't really want to be explaining memory addresses to a new programmer who doesn't understand memory layout and maybe doesn't even understand arrays yet.




                                            A simple and short example.

                                            We have a list of elements aligned one after the other. The start of this list, the first element is flagged with a pin.

                                            To get the first element, we go to where the pin is.

                                            To get the second element, we need to go to the pin plus one element.

                                            Starting at zero the computer can simply calculate where to go from the start location.



                                            More thoughts on that.

                                            Counting starts with "one" for the first element. Even for programmers. But programmers don't count elements when they start at zero, they give them names. These names start at the first number that can be built with digits. Zero denotes "nothing" but is the first valid number.




                                            couldn't a modern compiler often optimize this away?




                                            I think it can't. How? The calculation described above is fundamental, the CPU does it like that. A compiler can't optimize necessary calculations away.






                                            share|improve this answer








                                            New contributor




                                            puck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                            Check out our Code of Conduct.









                                            There are many answers but I miss an attempt to make it short and comprehensible for non programmers.




                                            I don't really want to be explaining memory addresses to a new programmer who doesn't understand memory layout and maybe doesn't even understand arrays yet.




                                            A simple and short example.

                                            We have a list of elements aligned one after the other. The start of this list, the first element is flagged with a pin.

                                            To get the first element, we go to where the pin is.

                                            To get the second element, we need to go to the pin plus one element.

                                            Starting at zero the computer can simply calculate where to go from the start location.



                                            More thoughts on that.

                                            Counting starts with "one" for the first element. Even for programmers. But programmers don't count elements when they start at zero, they give them names. These names start at the first number that can be built with digits. Zero denotes "nothing" but is the first valid number.




                                            couldn't a modern compiler often optimize this away?




                                            I think it can't. How? The calculation described above is fundamental, the CPU does it like that. A compiler can't optimize necessary calculations away.







                                            share|improve this answer








                                            New contributor




                                            puck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                            Check out our Code of Conduct.









                                            share|improve this answer



                                            share|improve this answer






                                            New contributor




                                            puck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                            Check out our Code of Conduct.









                                            answered yesterday









                                            puck

                                            1112




                                            1112




                                            New contributor




                                            puck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                            Check out our Code of Conduct.





                                            New contributor





                                            puck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                            Check out our Code of Conduct.






                                            puck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                            Check out our Code of Conduct.




















                                                up vote
                                                0
                                                down vote













                                                Languages which start from 0 are currently popular but there are others which start from 1. These examples are quite old. Many of the start from 0 languages are derived from or inspired by C.



                                                Cobol is not fashionable now but it is still an important language in business and its arrays start at 1. RPG (not role playing games) also has arrays which start from 1. RPG is ugly and horrible but it is also popular in business. My Fortran is rather rusty but I think that it also started at 1. Very long ago, I used Algol and you could choose the starting index 0, 1, or even negative. For some applications, negative indexes e.g. from -10 to +10, were convenient. I am not sure whether this was a standard feature or just one of the dialect that I used. Things were not so standardised back then.



                                                Edited to remove possible unintended offence.






                                                share|improve this answer










                                                New contributor




                                                badjohn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                Check out our Code of Conduct.





















                                                  up vote
                                                  0
                                                  down vote













                                                  Languages which start from 0 are currently popular but there are others which start from 1. These examples are quite old. Many of the start from 0 languages are derived from or inspired by C.



                                                  Cobol is not fashionable now but it is still an important language in business and its arrays start at 1. RPG (not role playing games) also has arrays which start from 1. RPG is ugly and horrible but it is also popular in business. My Fortran is rather rusty but I think that it also started at 1. Very long ago, I used Algol and you could choose the starting index 0, 1, or even negative. For some applications, negative indexes e.g. from -10 to +10, were convenient. I am not sure whether this was a standard feature or just one of the dialect that I used. Things were not so standardised back then.



                                                  Edited to remove possible unintended offence.






                                                  share|improve this answer










                                                  New contributor




                                                  badjohn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                  Check out our Code of Conduct.



















                                                    up vote
                                                    0
                                                    down vote










                                                    up vote
                                                    0
                                                    down vote









                                                    Languages which start from 0 are currently popular but there are others which start from 1. These examples are quite old. Many of the start from 0 languages are derived from or inspired by C.



                                                    Cobol is not fashionable now but it is still an important language in business and its arrays start at 1. RPG (not role playing games) also has arrays which start from 1. RPG is ugly and horrible but it is also popular in business. My Fortran is rather rusty but I think that it also started at 1. Very long ago, I used Algol and you could choose the starting index 0, 1, or even negative. For some applications, negative indexes e.g. from -10 to +10, were convenient. I am not sure whether this was a standard feature or just one of the dialect that I used. Things were not so standardised back then.



                                                    Edited to remove possible unintended offence.






                                                    share|improve this answer










                                                    New contributor




                                                    badjohn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                    Check out our Code of Conduct.









                                                    Languages which start from 0 are currently popular but there are others which start from 1. These examples are quite old. Many of the start from 0 languages are derived from or inspired by C.



                                                    Cobol is not fashionable now but it is still an important language in business and its arrays start at 1. RPG (not role playing games) also has arrays which start from 1. RPG is ugly and horrible but it is also popular in business. My Fortran is rather rusty but I think that it also started at 1. Very long ago, I used Algol and you could choose the starting index 0, 1, or even negative. For some applications, negative indexes e.g. from -10 to +10, were convenient. I am not sure whether this was a standard feature or just one of the dialect that I used. Things were not so standardised back then.



                                                    Edited to remove possible unintended offence.







                                                    share|improve this answer










                                                    New contributor




                                                    badjohn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                    Check out our Code of Conduct.









                                                    share|improve this answer



                                                    share|improve this answer








                                                    edited 13 hours ago





















                                                    New contributor




                                                    badjohn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                    Check out our Code of Conduct.









                                                    answered yesterday









                                                    badjohn

                                                    1092




                                                    1092




                                                    New contributor




                                                    badjohn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                    Check out our Code of Conduct.





                                                    New contributor





                                                    badjohn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                    Check out our Code of Conduct.






                                                    badjohn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                    Check out our Code of Conduct.




















                                                        up vote
                                                        0
                                                        down vote













                                                        Counting is always 100% arbitrary. Counting from 0, from 1 and from 7 - all make exactly same sense. Our reliance on indexing from 1 in real life is no different than our reliance on 10 as base of positional system. It's nothing but a convention.



                                                        The only issue is "How do I remember where do we agreed to start counting at?". From there comes the lead-on question: "What is the default value for integer variable?" or "If you started with a freshly initialized integer, what would you think would be it's value?"



                                                        And this is the reason why we start at 0: Integers start at 0, so it's helpful to map the first entry of an array to the first value of a variable capable of indexing it.






                                                        share|improve this answer
























                                                          up vote
                                                          0
                                                          down vote













                                                          Counting is always 100% arbitrary. Counting from 0, from 1 and from 7 - all make exactly same sense. Our reliance on indexing from 1 in real life is no different than our reliance on 10 as base of positional system. It's nothing but a convention.



                                                          The only issue is "How do I remember where do we agreed to start counting at?". From there comes the lead-on question: "What is the default value for integer variable?" or "If you started with a freshly initialized integer, what would you think would be it's value?"



                                                          And this is the reason why we start at 0: Integers start at 0, so it's helpful to map the first entry of an array to the first value of a variable capable of indexing it.






                                                          share|improve this answer






















                                                            up vote
                                                            0
                                                            down vote










                                                            up vote
                                                            0
                                                            down vote









                                                            Counting is always 100% arbitrary. Counting from 0, from 1 and from 7 - all make exactly same sense. Our reliance on indexing from 1 in real life is no different than our reliance on 10 as base of positional system. It's nothing but a convention.



                                                            The only issue is "How do I remember where do we agreed to start counting at?". From there comes the lead-on question: "What is the default value for integer variable?" or "If you started with a freshly initialized integer, what would you think would be it's value?"



                                                            And this is the reason why we start at 0: Integers start at 0, so it's helpful to map the first entry of an array to the first value of a variable capable of indexing it.






                                                            share|improve this answer












                                                            Counting is always 100% arbitrary. Counting from 0, from 1 and from 7 - all make exactly same sense. Our reliance on indexing from 1 in real life is no different than our reliance on 10 as base of positional system. It's nothing but a convention.



                                                            The only issue is "How do I remember where do we agreed to start counting at?". From there comes the lead-on question: "What is the default value for integer variable?" or "If you started with a freshly initialized integer, what would you think would be it's value?"



                                                            And this is the reason why we start at 0: Integers start at 0, so it's helpful to map the first entry of an array to the first value of a variable capable of indexing it.







                                                            share|improve this answer












                                                            share|improve this answer



                                                            share|improve this answer










                                                            answered 12 hours ago









                                                            Agent_L

                                                            1113




                                                            1113




















                                                                up vote
                                                                0
                                                                down vote













                                                                You give the answer yourself in the third bullet point, and you dismiss it too easily.



                                                                Let me delve into my personal experience from when I learned C in the mid-1980s. I remember when for the first I time saw 68k assembler code produced from indexing an array in C and realized that variables are just constant addresses, and indices are just offsets to them, so that addressing an array element a[i] could be understood as *(a+i) which simply was a readily available adressing mode in machine code if address a was already in a register.



                                                                It was a revelation on many levels: What C is (a macro assembler with a few bells and whistles plus standard library), what a compiler does, under what constraints programming languages work, and why C was so fast.



                                                                Why do you want to deprive your students of this insight? I think teaching arrays (or any programming, really) benefits tremendously from teaching memory addresses and some rudimentary assembler, so just go for it. All language abstraction is operating under the constraints of the metal. Your students will never understand why certain seemingly simple things are expensive or impossible if they don't know what they are actually doing.1



                                                                To sum up, essentially your third bullet point is the reason for the decision by the designers of C (or probably rather, BCPL or B) to start indexing at 0. Saving a subtraction at each element access, i.e. in many hot loops, was certainly highly relvant in 1970. True, today these original reasons are largely irrelevant; but today we have 45 years of code and a diverse C-rooted language tree. Regarding these languages we are locked in for good. As Jörg correctly mentioned in another answer, the decision was made differently for many other languages, probably not coincidentally some for which speed is secondary and some who target a lay audience.



                                                                1Don't get me wrong, I like abstraction. Having had the glimpse under the hood lets me actually appreciate the saftey, correctness and comfort provided by high-level languages and libraries.




                                                                share|improve this answer


























                                                                  up vote
                                                                  0
                                                                  down vote













                                                                  You give the answer yourself in the third bullet point, and you dismiss it too easily.



                                                                  Let me delve into my personal experience from when I learned C in the mid-1980s. I remember when for the first I time saw 68k assembler code produced from indexing an array in C and realized that variables are just constant addresses, and indices are just offsets to them, so that addressing an array element a[i] could be understood as *(a+i) which simply was a readily available adressing mode in machine code if address a was already in a register.



                                                                  It was a revelation on many levels: What C is (a macro assembler with a few bells and whistles plus standard library), what a compiler does, under what constraints programming languages work, and why C was so fast.



                                                                  Why do you want to deprive your students of this insight? I think teaching arrays (or any programming, really) benefits tremendously from teaching memory addresses and some rudimentary assembler, so just go for it. All language abstraction is operating under the constraints of the metal. Your students will never understand why certain seemingly simple things are expensive or impossible if they don't know what they are actually doing.1



                                                                  To sum up, essentially your third bullet point is the reason for the decision by the designers of C (or probably rather, BCPL or B) to start indexing at 0. Saving a subtraction at each element access, i.e. in many hot loops, was certainly highly relvant in 1970. True, today these original reasons are largely irrelevant; but today we have 45 years of code and a diverse C-rooted language tree. Regarding these languages we are locked in for good. As Jörg correctly mentioned in another answer, the decision was made differently for many other languages, probably not coincidentally some for which speed is secondary and some who target a lay audience.



                                                                  1Don't get me wrong, I like abstraction. Having had the glimpse under the hood lets me actually appreciate the saftey, correctness and comfort provided by high-level languages and libraries.




                                                                  share|improve this answer
























                                                                    up vote
                                                                    0
                                                                    down vote










                                                                    up vote
                                                                    0
                                                                    down vote









                                                                    You give the answer yourself in the third bullet point, and you dismiss it too easily.



                                                                    Let me delve into my personal experience from when I learned C in the mid-1980s. I remember when for the first I time saw 68k assembler code produced from indexing an array in C and realized that variables are just constant addresses, and indices are just offsets to them, so that addressing an array element a[i] could be understood as *(a+i) which simply was a readily available adressing mode in machine code if address a was already in a register.



                                                                    It was a revelation on many levels: What C is (a macro assembler with a few bells and whistles plus standard library), what a compiler does, under what constraints programming languages work, and why C was so fast.



                                                                    Why do you want to deprive your students of this insight? I think teaching arrays (or any programming, really) benefits tremendously from teaching memory addresses and some rudimentary assembler, so just go for it. All language abstraction is operating under the constraints of the metal. Your students will never understand why certain seemingly simple things are expensive or impossible if they don't know what they are actually doing.1



                                                                    To sum up, essentially your third bullet point is the reason for the decision by the designers of C (or probably rather, BCPL or B) to start indexing at 0. Saving a subtraction at each element access, i.e. in many hot loops, was certainly highly relvant in 1970. True, today these original reasons are largely irrelevant; but today we have 45 years of code and a diverse C-rooted language tree. Regarding these languages we are locked in for good. As Jörg correctly mentioned in another answer, the decision was made differently for many other languages, probably not coincidentally some for which speed is secondary and some who target a lay audience.



                                                                    1Don't get me wrong, I like abstraction. Having had the glimpse under the hood lets me actually appreciate the saftey, correctness and comfort provided by high-level languages and libraries.




                                                                    share|improve this answer














                                                                    You give the answer yourself in the third bullet point, and you dismiss it too easily.



                                                                    Let me delve into my personal experience from when I learned C in the mid-1980s. I remember when for the first I time saw 68k assembler code produced from indexing an array in C and realized that variables are just constant addresses, and indices are just offsets to them, so that addressing an array element a[i] could be understood as *(a+i) which simply was a readily available adressing mode in machine code if address a was already in a register.



                                                                    It was a revelation on many levels: What C is (a macro assembler with a few bells and whistles plus standard library), what a compiler does, under what constraints programming languages work, and why C was so fast.



                                                                    Why do you want to deprive your students of this insight? I think teaching arrays (or any programming, really) benefits tremendously from teaching memory addresses and some rudimentary assembler, so just go for it. All language abstraction is operating under the constraints of the metal. Your students will never understand why certain seemingly simple things are expensive or impossible if they don't know what they are actually doing.1



                                                                    To sum up, essentially your third bullet point is the reason for the decision by the designers of C (or probably rather, BCPL or B) to start indexing at 0. Saving a subtraction at each element access, i.e. in many hot loops, was certainly highly relvant in 1970. True, today these original reasons are largely irrelevant; but today we have 45 years of code and a diverse C-rooted language tree. Regarding these languages we are locked in for good. As Jörg correctly mentioned in another answer, the decision was made differently for many other languages, probably not coincidentally some for which speed is secondary and some who target a lay audience.



                                                                    1Don't get me wrong, I like abstraction. Having had the glimpse under the hood lets me actually appreciate the saftey, correctness and comfort provided by high-level languages and libraries.





                                                                    share|improve this answer














                                                                    share|improve this answer



                                                                    share|improve this answer








                                                                    edited 2 hours ago

























                                                                    answered 10 hours ago









                                                                    Peter A. Schneider

                                                                    27817




                                                                    27817




















                                                                        up vote
                                                                        -3
                                                                        down vote













                                                                        "Thing zero"



                                                                        I have nothing, I have one thing, I have two things...



                                                                        0,1,2...



                                                                        0x00, 0x01, 0x02...



                                                                        0000, 0001, 0010...



                                                                        There is nothing in my register, there is one thing in my register, there are two things in my register.



                                                                        There is nothing in my array, there is one thing in my array, there are two things in my array.



                                                                        If you started at one, you'd always have a minimum of one thing.






                                                                        share|improve this answer








                                                                        New contributor




                                                                        Munkee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                                        Check out our Code of Conduct.













                                                                        • 5




                                                                          But myint[0] isn't nothing, it's something.
                                                                          – Ben I.♦
                                                                          2 days ago















                                                                        up vote
                                                                        -3
                                                                        down vote













                                                                        "Thing zero"



                                                                        I have nothing, I have one thing, I have two things...



                                                                        0,1,2...



                                                                        0x00, 0x01, 0x02...



                                                                        0000, 0001, 0010...



                                                                        There is nothing in my register, there is one thing in my register, there are two things in my register.



                                                                        There is nothing in my array, there is one thing in my array, there are two things in my array.



                                                                        If you started at one, you'd always have a minimum of one thing.






                                                                        share|improve this answer








                                                                        New contributor




                                                                        Munkee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                                        Check out our Code of Conduct.













                                                                        • 5




                                                                          But myint[0] isn't nothing, it's something.
                                                                          – Ben I.♦
                                                                          2 days ago













                                                                        up vote
                                                                        -3
                                                                        down vote










                                                                        up vote
                                                                        -3
                                                                        down vote









                                                                        "Thing zero"



                                                                        I have nothing, I have one thing, I have two things...



                                                                        0,1,2...



                                                                        0x00, 0x01, 0x02...



                                                                        0000, 0001, 0010...



                                                                        There is nothing in my register, there is one thing in my register, there are two things in my register.



                                                                        There is nothing in my array, there is one thing in my array, there are two things in my array.



                                                                        If you started at one, you'd always have a minimum of one thing.






                                                                        share|improve this answer








                                                                        New contributor




                                                                        Munkee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                                        Check out our Code of Conduct.









                                                                        "Thing zero"



                                                                        I have nothing, I have one thing, I have two things...



                                                                        0,1,2...



                                                                        0x00, 0x01, 0x02...



                                                                        0000, 0001, 0010...



                                                                        There is nothing in my register, there is one thing in my register, there are two things in my register.



                                                                        There is nothing in my array, there is one thing in my array, there are two things in my array.



                                                                        If you started at one, you'd always have a minimum of one thing.







                                                                        share|improve this answer








                                                                        New contributor




                                                                        Munkee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                                        Check out our Code of Conduct.









                                                                        share|improve this answer



                                                                        share|improve this answer






                                                                        New contributor




                                                                        Munkee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                                        Check out our Code of Conduct.









                                                                        answered 2 days ago









                                                                        Munkee

                                                                        1




                                                                        1




                                                                        New contributor




                                                                        Munkee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                                        Check out our Code of Conduct.





                                                                        New contributor





                                                                        Munkee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                                        Check out our Code of Conduct.






                                                                        Munkee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                                                        Check out our Code of Conduct.







                                                                        • 5




                                                                          But myint[0] isn't nothing, it's something.
                                                                          – Ben I.♦
                                                                          2 days ago













                                                                        • 5




                                                                          But myint[0] isn't nothing, it's something.
                                                                          – Ben I.♦
                                                                          2 days ago








                                                                        5




                                                                        5




                                                                        But myint[0] isn't nothing, it's something.
                                                                        – Ben I.♦
                                                                        2 days ago





                                                                        But myint[0] isn't nothing, it's something.
                                                                        – Ben I.♦
                                                                        2 days ago


















                                                                         

                                                                        draft saved


                                                                        draft discarded















































                                                                         


                                                                        draft saved


                                                                        draft discarded














                                                                        StackExchange.ready(
                                                                        function ()
                                                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcseducators.stackexchange.com%2fquestions%2f5023%2fwhy-do-we-count-starting-from-zero%23new-answer', 'question_page');

                                                                        );

                                                                        Post as a guest













































































                                                                        Comments

                                                                        Popular posts from this blog

                                                                        What does second last employer means? [closed]

                                                                        Installing NextGIS Connect into QGIS 3?

                                                                        One-line joke