... In many parts of programming.
Half-open interval denoted as [begin, end) (end is not included in interval).
random.randrange in Python is also half-open, like range():
random.randrange(stop) random.randrange(start, stop[, step]) Return a randomly selected element from range(start, stop, step). This is roughly equivalent to choice(range(start, stop, step)) but supports arbitrarily large ranges and is optimized for common cases. The positional argument pattern matches the range() function.
( https://docs.python.org/3/library/random.html )
In C++:
int∗ find(int∗ first, int∗ last, int v)
// find x in [first:last)
{
while (first!=last && ∗first!=v)
++first;
return first;
}
...
The simple version of accumulate() adds elements of a sequence using their + operator:
template<typename In, typename T>
T accumulate(In first, In last, T init)
{
for (; first!=last; ++first) // for all elements in [first:last)
init = init + ∗first;
// plus
return init;
}
...
// Sample the remaining values in [first+n:last) by selecting a random
// number r in the range [0:k], and, if r<n, replace it.
...
for (Size k = n; first!=last; ++first,++k) {
Size r = dist(gen,Param{0,k});
if(r < n)
∗(result + r) = ∗first;
}
...
Given a sorted sequence [first:last), equal_range() will return the pair representing the subsequence
that matches the predicate cmp.
( Bjarne Stroustrup - TC++PL 4ed (2013) )
Also:
[begin, end) – iterator pairs, e.g. ranges made by implicit conversion from containers. All algorithms that take iterator pairs now have overloads that accept ranges (e.g. ranges::sort) ... begin + [0, size) – counted sequences, e.g. range returned by views::counted
( src )
Half-open intervals also called 'right-open' (open at right):
All algorithms in STL are implemented with right-open intervals [b, e) operating on the value referred to by b, which is then incremented until b = e. Therefore, [x, x) represents an empty interval.
( Peter Gottschling - Discovering Modern C++ )
Also in Golang:
As in most other programming languages, all indexing in Go uses half-open intervals that include the first index but exclude the last, because it simplifies logic. For example, the slice s[m:n], where 0 ≤ m ≤ n ≤ len(s), contains n-m elements.
( The Go Programming Language: A Tutorial )
As in most other programming languages, all indexing in Go uses half-open intervals that include the first index but exclude the last, because it simplifies logic. For example, the slice s[m:n], where 0 ≤ m ≤ n ≤ len(s), contains n-m elements.
( Alan A. A. Donovan, Brian W. Kernighan - The Go Programming Language (2015) )
Also, in .../src/math/rand/v2/rand.go:
// Int64N returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n).
// It panics if n <= 0.
func (r *Rand) Int64N(n int64) int64 {
...
// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0).
func (r *Rand) Float64() float64 {
Also, in POSIX.
These functions generates a number between 0.0 and 0.99999...., but not 1.0:
The drand48() and erand48() functions shall return non-negative,
double-precision, floating-point values, uniformly distributed over
the interval [0.0,1.0).
And this, between 0 and 0x7fffffff (random low 32 bits), but not 2^31 (0x80000000):
The lrand48() and nrand48() functions shall return non-negative,
long integers, uniformly distributed over the interval [0,2^31).
One can say/write simpler: this function generates 32 random bits, including sign. But, 2^31=0x80000000, and this is negative number in two's complement, so this is why interval looks so confusing:
The mrand48() and jrand48() functions shall return signed long
integers uniformly distributed over the interval [-2^31,2^31).
Half-open intervals are natural in programming.
.begin() in C++ STL .begin() points to a first elements and .end() to whatever after the last element. (Also called sentinel node.) This simplifies all the algorithms.
Hence, a loop in C++ STL is usually:
for (auto it=some_list.begin(); it!=some_list.end(); it++)
{
// use *it;
};
Formally, elements in half-open interval [some_list.begin(), some_list.end()) are enumerated.
Now a thought experiment. Imagine the .end() pointing to the last element and try to rewrite this loop... Would it be as concise as we have it already? Probably not.

Some time ago (before 24-Mar-2025) there was Disqus JS script for comments. I dropped it --- it was so motley, distracting, animated, with too much ads. I never liked it. Also, comments din't appeared correctly (Disqus was buggy). Also, my blog is too chamberlike --- not many people write comments here. So I decided to switch to the model I once had at least in 2020 --- send me your comments by email (don't forget to include URL to this blog post) and I will copy&paste it here manually.
Let's party like it's ~1993-1996, in this ultimate, radical and uncompromisingly primitive pre-web1.0-style blog and website. This website is best viewed under lynx/links/elinks/w3m.