Apologies if this appears dumb. After going through the link I still could not understand why is it ok to exclude the upper bound while including the lower bound? Is it because the lower bound is fixed as 0 is the smallest natural number? Or is there some other reason.
Dijkstra explains it pretty clearly - there are two main reasons.
The first is so that the number of elements in the array/list/vector/collection is given by upper-lower.
The second is so that successive intervals re-use the same number, the upper bound of one becoming the lower bound of the next.
This is python we can have:
L[:3], L[3:6], L[6:23], L[23:40], L[40:]
With the repeated numbers we know that all elements of L have been included. Further, we know that given:
L[start:end]
... then (provided L had at least "end" elements to start with) the resulting length is end-start. If you included the end point then the length would be end-start+1 which is fertile ground for fence-post errors.
But both of those things would be true if you include the upper bound and don't include the lower bound. I.e. if an array with bounds 0 and 4 had items in positions 1, 2, 3, and 4.
Yes, and that question is covered in the Dijkstra paper.
If you're talking about numbers from 13 onwards, it doesn't really make sense to talk about numbers greater than 12. More specifically, if you start counting from 0 then it feels (to me) more natural to include the lower bound.
If you talk about {5 .. 13} then it feels easier to say
"From 5 up to (but not including) 13,"
rather than saying
"From 5, er, sorry, no, from *6* up to and including 13."
There is a question of taste here, as well as background and experience. Don't expect it to be "objectively proven."
In the end it is all about convention, and what ends up making code cleaner, less error-prone, and more aesthetically pleasing. As I say, there are questions of taste and experience. Personally I find the Dijkstra/Python method for more consistent and pleasing than the alternatives.
Another reason: Wrap-around with modular reduction is a snug fit, so it's L[i % n] rather than L[1 + i % n]. You could have taken 1, 2, ..., n or indeed any set of n integers with distinct residue classes modulo n as the representatives, but the standard choice in mathematics is 0, 1, ..., n-1 for consistency with the division theorem.
It is often very inconvenient when mathematicians number from 1 instead of 0. A classic example is with Fourier matrices. Let w be a primitive nth root of unity. Then numbering as computer scientists, starting with 0, the formula is F(i,j) = w^(i j). But using the mathematician's convention, it is F(i,j) = w^((i-1)(j-1)). The same issue exists with all Vandermonde matrices.
Few people seem to know that we have real and valid reasons for indexing from 0 instead of 1.