To clarify the problem, when we have to describe a range of values, there are typically three ways that programmers use a pair of integrals to describe the range:
- First item, number of items ("start/length")
- First item, last included item ("start/end")
- Fisrt item, one past last item ("start/end+1")
First, why not start/end? Well, the nice thing about start/end+1 is that the length of the range is just end-start. When you use start/end, you have to do the awkward (end-start+1).
Range checks also become inconsistent...basically you want to have your regions defined inclusive on one side and exclusive on the other. In other words, being in the range should be true if x >= x1 && x < x2. What's good about this is that if the end value of one range is equal to the start value of another, the two perfectly align, and the two cover an interval completely. With start/end notation, you get tons of off-by-one situations.
Similarly, start/length simply requires you to write more code. Consider start/end+1...a number of useful operations become trivial:
- The union of [x1,x2) and [y1,y2) is just [min(x1,y1),max(x2,y2))
- The intersection of the two is [max(x1,y1),min(x2,y2))
- A range is empty if x2 <= x1
- Containment and asymmetric set differences are all equally clean.