quel est un moyen efficace de trouver des décimales répétitives

24

J'essaie de trouver un algorithme efficace en Java pour trouver la partie décimale répétitive de deux entiers aet ba/b.

par exemple. 5/7 = 0,714258 714258 ....

Je ne connais actuellement que la méthode de la division longue.

Jun Hao
la source
2
Vous avez donc a = 5 et b = 7, et vous pouvez calculer a / b en virgule flottante assez facilement, mais ce que vous voulez savoir, c'est qu'il se répète après 6 décimales?
Sparr

Réponses:

10

Je crois qu'il y a deux approches générales ici, vous pouvez essentiellement rechercher par "force brute" la chaîne répétitive la plus longue, ou vous pouvez la résoudre comme un problème de théorie des nombres.

Cela fait longtemps que je n'ai pas rencontré ce problème, mais un cas spécial (1 / n) est le problème # 26 sur Project Euler, donc vous pourrez peut-être trouver plus d'informations en recherchant des solutions efficaces pour ce nom spécifique. Une recherche nous mène au site Web d'Eli Bendersky, où il explique sa solution . Voici une partie de la théorie de la page Expansion décimale de Mathworld :

Toute fraction non m/nrégulière est périodique et a une période lambda(n)indépendante de m, qui est au plus n-1 longue. Si nest relativement premier à 10, alors la période lambda(n)de m/nest un diviseur de phi(n)et a au plus des phi(n)chiffres, où phiest la fonction totiente. Il s'avère que lambda(n)c'est l' ordre multiplicatif de 10 (mod n) (Glaisher 1878, Lehmer 1941). Le nombre de chiffres dans la partie répétitive de l'expansion décimale d'un nombre rationnel peut également être trouvé directement à partir de l'ordre multiplicatif de son dénominateur.

Ma théorie des nombres est un peu rouillée pour le moment, donc le mieux que je puisse faire est de vous orienter dans cette direction.

Daniel B
la source
8

Laissez n < d, et vous essayez de comprendre la partie répétitive de n/d. Soit ple nombre de chiffres dans la partie répétitive: alors n/d = R * 10^(-p) + R * 10^(-2p) + ... = R * ((10^-p)^1 + (10^-p)^2 + ...). La partie entre crochets est une série géométrique, égale à 1/(10^p - 1).

Alors n / d = R / (10^p - 1). Réorganisez pour obtenir R = n * (10^p - 1) / d. Pour trouver R, bouclez pde 1 à l'infini et arrêtez dès que la ddivision est égale n * (10^p - 1).

Voici une implémentation en Python:

def f(n, d):
    x = n * 9
    z = x
    k = 1
    while z % d:
        z = z * 10 + x
        k += 1
    return k, z / d

( kgarde une trace de la longueur de la séquence répétée, afin que vous puissiez faire la distinction entre 1/9 et 1/99, par exemple)

Notez que cette implémentation (ironiquement) boucle pour toujours si l'expansion décimale est finie, mais se termine si elle est infinie! Vous pouvez vérifier ce cas, car n/dil n'aura une représentation décimale finie que si tous les facteurs premiers dqui ne sont pas 2 ou 5 sont également présents dans n.

valtron
la source
1
Cette réponse semble correcte. La méthode est basée sur la "règle" suivante: 0.123123... = 123/999 0.714258714258... = 714258/999999 (=5/7)etc.
VENEZ DU
4
Il échoue des cas comme 1/6 ou 5/12: \
razpeitia
1
@razpeitia J'ai créé quelque chose de similaire, mais qui fonctionne dans tous les cas (y compris la division entière). Départ: codepad.org/hKboFPd2
Tigran Saluev
J'ai fait une implémentation javascript similaire à celle de @ TigranSaluev sur github.com/Macil/cycle-division
Macil
2

Division longue? : /

Transformez le résultat en chaîne, puis appliquez-lui cet algorithme . Utilisez BigDecimal si votre chaîne n'est pas assez longue avec des types ordinaires.

Robert Harvey
la source
4
"Transformez-le en chaîne" pourrait nécessiter des calculs de précision arbitraires et une très longue chaîne pour calculer deux copies de la partie répétitive de la chaîne (et comment savez-vous quand arrêter de calculer? .121212312121231212123 ... serait un problème)
Sparr
@Sparr La longueur de la répétition est toujours inférieure au dénominateur.
@MichaelT Je n'étais pas au courant de cela. Si vrai, la précision n'est pas précisément "arbitraire", mais peut être arbitrairement élevée selon le dénominateur.
Sparr
Je ne pense pas que l'algorithme auquel vous vous connectez fonctionnerait sans modification. Il comprend des répétitions qui se chevauchent et il recherche dans toute la chaîne (pas seulement pour les correspondances consécutives). Par exemple, la sous-chaîne répétée la plus longue dans "banane" est "ana".
Web_Designer