Rationals are enumerable. For example this code finds k-th rational in open interval 0..1, with ordering that {n1, d1}
is before {n2, d2}
if (d1&
I strongly suggest looking at The "guess the number" game for arbitrary rational numbers? for some inspiration about your underlying problem.
If your goal is to be approximately uniform ASAP, and you don't mind picking different rationals with different probabilities, the following algorithm should be efficient.
lower = fractions.Fraction(0)
upper = fractions.Fraction(1)
while lower < upper:
mid = (upper + lower)/2
if 0 == random_bit():
upper = largest_rational_under(mid, denominator_bound)
else:
lower = smallest_rational_over_or_equal(mid, denominator_bound)
Note that both of those two helper functions can be calculated by walking the Stern-Brocot Tree towards the mid. Also note that, with some minor modification, you can easily transform this into an iterative algorithm that spits out a sequence of rational numbers, and eventually will converge with equal likelihood anywhere in the interval. I consider that property to be kind of nice.
If you want the exact distribution that you originally specified, and rand(n)
gives you a random integer from 1
to n
, then the following pseudocode will work for denominator bound n
:
Try:
k = rand(n * (n+1) / 2)
do binary search for largest j with j * (j-1) / 2 < k
i = k - (j * (j-1) / 2)
if (i, j) are not relatively prime:
redo Try
answer = i/j
On average for large n
you'll have to Try
about 2.55 times. So in practice this should be pretty efficient.