関連する数学は、連分数に関するウィキペディアの記事で説明されています。簡単に言うと、下端と上端の 2 つの連分数を計算し、共通端点の後で連分数が切り捨てられる 4 つの組み合わせを試します。
これが Python の実装です。
import fractions
F = fractions.Fraction
def to_continued_fractions(x):
a = []
while True:
q, r = divmod(x.numerator, x.denominator)
a.append(q)
if r == 0:
break
x = F(x.denominator, r)
return (a, a[:-1] + [a[-1] - 1, 1])
def combine(a, b):
i = 0
while i < len(a) and i < len(b):
if a[i] != b[i]:
return a[:i] + [min(a[i], b[i]) + 1]
i += 1
if i < len(a):
return a[:i] + [a[i] + 1]
if i < len(b):
return a[:i] + [b[i] + 1]
assert False
def from_continued_fraction(a):
x = fractions.Fraction(a[-1])
for i in range(len(a) - 2, -1, -1):
x = a[i] + 1 / x
return x
def between(x, y):
def predicate(z):
return x < z < y or y < z < x
return predicate
def simplicity(x):
return x.numerator
def simplest_between(x, y):
return min(filter(between(x, y), (from_continued_fraction(combine(a, b)) for a in to_continued_fractions(x) for b in to_continued_fractions(y))), key=simplicity)
print(simplest_between(F(1110, 416), F(1110, 417)))
print(simplest_between(F(500, 166), F(500, 167)))