Есть отличный алгоритм основанный на дереве Штерна-Броко. вот моя реализация.
Код
uint aim = 0.456;
uint guess;
uint max_denominator = 8192;
uint item_1_p = 0;
uint item_1_q = 1;
uint item_2_p = 1;
uint item_2_q = 2;
uint item_3_p = 1;
uint item_3_q = 1;
while(1){
guess = (double)item_2_p/ (double)item_2_q;
if (aim<=guess) {
item_3_p = item_2_p;
item_3_q = item_2_q;
} else{
item_1_p = item_2_p;
item_1_q = item_2_q;
}
if (item_1_q + item_3_q>max_denominator) break;
item_2_p = item_1_p + item_3_p;
item_2_q = item_1_q + item_3_q;
}
По итогу в item_2_p и item_2_q хранятся числитель и знаменатель дроби минимально отличающейся от aim при заданном максимальном знаменателе. Изменяя значения item_1_p item_1_q item_3_p item_3_q задаём границы для поиска решения.