Search code examples
algorithmmathoptimizationmathematical-optimizationfractions

Finding the closest integer fraction to a given random real between 0..1, given ranges of numerator and denominator


Given two ranges of positive integers x: [1 ... n] and y: [1 ... m] and random real R from 0 to 1, I need to find the pair of elements (i,j) from x and y such that x_i / y_j is closest to R.

What is the most efficient way to find this pair?


Solution

  • Using Farey sequence

    This is a simple and mathematically beautiful algorithm to solve this: run a binary search, where on each iteration the next number is given by the mediant formula (below). By the properties of the Farey sequence that number is the one with the smallest denominator within that interval. Consequently this sequence will always converge and never 'miss' a valid solution.

    In pseudocode:

    input: m, n, R
    
    a_num = 0, a_denom = 1
    b_num = 1, b_denom = 1
    
    repeat:
        -- interestingly c_num/c_denom is already in reduced form
        c_num = a_num + b_num
        c_denom = a_denom + b_denom
    
        -- if the numbers are too big, return the closest of a and b
        if c_num > n or c_denom > m then
            if R - a_num/a_denom < b_num/b_denom - R then
                return a_num, a_denom
            else
                return b_num, b_denom
    
        -- adjust the interval:
        if c_num/c_denom < R then
            a_num = c_num, a_denom = c_denom
        else
            b_num = c_num, b_denom = c_denom
    
    goto repeat
    

    Even though it's fast on average (my educated guess that it's O(log max(m,n))), it can still be slow if R is close to a fraction with a small denominator. For example finding an approximation to 1/1000000 with m = n = 1000000 will take a million iterations.