There is a 30 year old book that imho has never been bettered: Numerical Recipes in C. You should be able to pick up a 2nd hand copy fairly cheaply. e.g.
Ah, you have discovered that unfortunate paper by Dijkstra. That paper should have never been written. The paper was an emotional response to an emotional incident, if you read the end of the paper, and the mathematical idea picked up to rationalizes for his case was what we would be called, looking for an argument to conform to his view. Something we often see in social media these days, back then social media was publishing in newspapers, journals, magazines and books.
> Have you ever wondered why they are always implemented
They are not always implemented so. Fortran and Pascal did not do so, at least for static arrays. In Numerical Recipes in C authors do a trick with decrementing the array pointer by -1, so they can use [1,length] interval to make their algorithms prettier (which they abandoned in their C++ version of the book, probably because people are used to type length-1 everywhere :-)).
Anyway, that is something wrong with the whole idea: well it depends. Most importantly, numbering does not start at zero in everyday talk. We don't say 0th person in the queue, we say the first person in the queue; we say the 2nd seat on the 3rd row, 1st day of May, not the 0th day of May and so on. This is not how mathematics use it, either. So at least indexing should not start at zero. By using this convention in computer science, where indexing goes from [0,length), we have introduced entire new concept that we have to teach to studends, and that unfortunately goes against normal use in everyday language. I wonder how many off-by-one errors have humanity done and how much money has those cost society in debugging. There is a nice joke about it too.
So why do we use [0,length) in computer science to index into arrays? I personally believe it is an implementation detail that leaked into the language design. I am speaking about the C language, and early C compilers that were a 1.5 pass compilers. I don't know if they exposed pointer arithmetic involved in arrays to make the compiler just slightly simpler and faster to implement, but what I do know is that it opened its own chapter in computer history (of errors). Compiler could have just as easily convert [0,length] into [0, length). Anyway it has creeped up from C to C++, Java, JavaScript, and C have probably got it over from its predecessors. For example Lisps are also using [0, length) in indexing and those are older than C. Pascal for example uses closed interval to access static arrays without problems, and the interval does not even have to start from 1, however they have messed up with "dynamic arrays", which do the same as C, since I guess they are using malloc & co (sbrk probably) under the hood. In numerical recipes in C, they use a little trick, they decrement the pointer to an array first, so they can use the closed interval. Fortran is an older language than C, and it uses indexing from 1 for static arrays too, and for long time Fortran was uses for "number crunching", so it was not about speed of produced machine code, but more about the compiler implementation. Might be also that they were really exposing the machine details, albeit I don't thing that array indexing is really a machine detail.
Whatever, there are some cases where open interval is more useful than closes one, for example when working with module operator and calculating indexes in arrays, but those are rather niche cases that compiler could have dealt for us. Today's compilers are so complex and do so many transformations for us, that I am really surprised why don't we see languages that rebel against this unnatural situation of indexing. Not even Rust that is so much about safe computing, and checks arrays for out of bounds errors (as well as Java) have not taken notice that off-by-one errors are completely necessary and could be probably reduced if people were not forced to write their loops like for (int i = 0; i < array.length -1; i++).
> With [a, b] you get a few edge cases, for one the length of [a, a-1] could be 0 as we saw earlier, or it could be negative if a < 1.
Is there some problem with negative indexes?
#include <stdio.h>
int main(int argc, char** argv) {
const int array[] = { -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 }; const int* it = &array[5];
printf("Value of index -3 is: %d\n", it[-3]); return 0; }
The run:
$ gcc -o test test.c ~/repos $ ./test Value of index -3 is: -3
Anyway; I understand what you mean. I think, we should probably not use the word length here, which is a measure of distance. Distance is, mathematically, defined as the difference of square roots (Pythagoras theorem), so length per definition can't be negative. We are (ab)using that word normally in programming, but here is good to remind us that we really mean number of elements in a set, not a geometrical measure, when we say length of some data structure. It is about counting, not measuring the distance, so to start with calculating the number of element by taking the difference of end points is obviously the wrong idea. By taking a difference of intervals of end points, you are actually talking about geometrical distance, when you really wish to speak about number of elements.
> splitting the hours in a day into two ranges, should result in 2 ranges with length 12, so that 12+12 = 24. This property is lost when using [a, b] ranges.
Let us use 6 + 6 = 12, just to type less:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] = 12 [1, 2, 3, 4, 5, 6] = 6 [7, 8, 9, 10, 11, 12] = 6 ------------------------------ 6 + 6 = 12
?
> I won't bore you with the details, but let's just say that the brilliant people at Xerox PARC tried them, and found that [a, b] ranges lead to buggier and more complex code.
I guess by now, we all are so indoctrinated by years of usage, that we take it for granted, and would probably make more off-by-one errors in language that tries to fix this concept and to use [1,length] interval to accessing arrays; but if we had a generation or two of young programmers growing up with concept where lengths are expressed in terms of [x,y] rather than [x,y), I belive we would look at it with different eyes. Mostly because an entire concept that students have to learn and get used to would go away. Anyway, Fortran programmers seems to have done fine with it; but I have no information how buggy Fortran code use to be (or still is :-)).
Observe, I am not saying you are very wrong in what you say; we live in a programming world in which we iterate from i =0 to i < length, and that is going nowhere in any near future. I have just tried to give a bit more perspective on this.
Chances are, either your first or second semester, you may start with C or C++ for algorithms and data structures. Here is a book from the creator of C++, that may get you what you need to be familiar with the language: http://www.stroustrup.com/4th.html
Or, if you are interested in C:
K&R C .
And last but not least, a book that I found fascinating was:
http://www.amazon.com/Numerical-Recipes-Scientific-Computing-Edition/dp/0521431085