I have a non-empty integer interval [a; b). I want to generate a random non-empty integer subinterval [c; d) (where a <= c and d <= b). The [c; d) interval must be uniformly distributed in the sense that every point in [a; b) must be equally likely to end up in [c; d).
I tried generating uniformly distributed c from [a; b - 1), and then uniformly distributed d from [c + 1; b), like this:
a = -100
b = 100
N = 10000
cs = np.random.randint(a, b - 1, N)
ds = np.random.randint(cs + 1, b)
But when measuring how often each point ends up being sampled, the the distribution is clearly non-unifrom:
import numpy as np
import matplotlib.pyplot as plt
hist = np.zeros(b - a, int)
for c, d in zip(cs, ds):
hist[c - a:d - a] += 1
plt.plot(np.arange(a, b), hist)
plt.show()

How do I do this correctly?

If you divide the range
[a,b)into N sections, and then select one of those sections at random, then the chance of selecting each point is uniform --1/N. It doesn't matter how you divide the range.Here's a solution along those lines that uses a pretty uniform selection of division points.