J'essaie de trouver un algorithme efficace en Java pour trouver la partie décimale répétitive de deux entiers a
et b
où a/b
.
par exemple. 5/7 = 0,714258 714258 ....
Je ne connais actuellement que la méthode de la division longue.
J'essaie de trouver un algorithme efficace en Java pour trouver la partie décimale répétitive de deux entiers a
et b
où a/b
.
par exemple. 5/7 = 0,714258 714258 ....
Je ne connais actuellement que la méthode de la division longue.
Réponses:
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/n
régulière est périodique et a une périodelambda(n)
indépendante dem
, qui est au plusn-1
longue. Sin
est relativement premier à 10, alors la périodelambda(n)
dem/n
est un diviseur dephi(n)
et a au plus desphi(n)
chiffres, oùphi
est la fonction totiente. Il s'avère quelambda(n)
c'est l' ordre multiplicatif de 10 (modn
) (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.
Laissez n < d
, et vous essayez de comprendre la partie répétitive de n/d
. Soit p
le 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 p
de 1 à l'infini et arrêtez dès que la d
division 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
( k
garde 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/d
il n'aura une représentation décimale finie que si tous les facteurs premiers d
qui ne sont pas 2 ou 5 sont également présents dans n
.
0.123123... = 123/999
0.714258714258... = 714258/999999 (=5/7)
etc.
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.