Random rational numbers generation

前端 未结 3 1339
失恋的感觉
失恋的感觉 2021-02-04 04:26

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&

3条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2021-02-04 04:49

    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.

提交回复
热议问题