Cela me rappelle le problème de la recherche de bonnes approximations rationnelles des nombres réels. La technique standard est une expansion en fractions continues :
def rationalizations(x):
assert 0 <= x
ix = int(x)
yield ix, 1
if x == ix: return
for numer, denom in rationalizations(1.0/(x-ix)):
yield denom + ix * numer, numer
Nous pourrions appliquer cela directement à l'approche de Jonathan Leffler et Sparr :
>>> a, b, c = 2.468, 3.700, 6.1699
>>> b/a, c/a
(1.4991896272285252, 2.4999594813614263)
>>> list(itertools.islice(rationalizations(b/a), 3))
[(1, 1), (3, 2), (925, 617)]
>>> list(itertools.islice(rationalizations(c/a), 3))
[(2, 1), (5, 2), (30847, 12339)]
en choisissant la première approximation suffisamment bonne dans chaque séquence. (3/2 et 5/2 ici.) Ou, au lieu de comparer directement 3.0/2.0 à 1.499189..., vous pourriez remarquer que 925/617 utilisent beaucoup plus grande entiers que 3/2, ce qui fait de 3/2 un excellent endroit pour s'arrêter.
Le nombre par lequel vous divisez ne devrait pas avoir beaucoup d'importance. (En utilisant a/b et c/b, vous obtenez 2/3 et 5/3, par exemple.) Une fois que vous avez des rapports entiers, vous pouvez affiner l'estimation implicite de la fondamentale en utilisant la régression linéaire de shsmurfy. Tout le monde y gagne !
2 votes
D'après votre autre question, vous détectez la fréquence des sons du piano. Notez que les pianos ne sont pas harmoniques. Les fréquences les plus élevées n'ont jamais été des multiples entiers de la fondamentale au départ : elles sont légèrement aiguës parce que la corde se comporte comme si elle était plus courte à des fréquences plus élevées. Pour cette raison, l'accordeur de piano étire légèrement la gamme pour minimiser les battements entre les partiels et maximiser la consonance : fr.wikipedia.org/wiki/Inharmonicity#Pianos