Algorithme pour trouver tous exactement les diviseurs d'un nombre entier donné
Je veux trouver tous exactement les diviseurs d'un nombre.
Actuellement j'ai ceci:
{
int n;
int i=2;
scanf("%d",&n);
while(i<=n/2)
{
if(n%i==0)
printf("%d,",i);
i++;
}
getch();
}
Est-il un moyen de l'améliorer?
Vous devez vous connecter pour publier un commentaire.
Tout d'abord, votre code doit avoir la condition de
i <= n/2
, sinon, il peut manquer l'un des facteurs, par exemple 6 ne sera pas imprimé si n=12.Exécuter la boucle à la racine carrée du nombre (ie.
i <= sqrt(n)
) et l'impression à la foisi
etn/i
(les deux seront des multiples de n).Remarque :
i*i == n
comme suggéré par @chepner.printf("%d,", i);printf("%d,", n/i);
àprintf("%d,", i); if(i != n/i){printf("%d,", n/i);}
.Pour un carré parfait, il ne sera pas imprimé deux fois de la racine.n/i !=i
par itération suri < sqrt(n)
, ce qui implique quen/i != i
, puis de vérifieri=sqrt(n)
en dehors de la boucle while comme un seul cas de bord.i <= sqrt(n)
promeut j'ai en double. Vous pouvez utiliseri <= (int)sqrt(n)
pour éviter cela. Il serait plus rapide de changerif (i != (n / i))
àif (i*i != n)
.Trouver tous les diviseurs en utilisant la fonction "recherche de tous les facteurs premiers" dans C (plus rapide)
et jusqu'à 18 chiffres.
La simple recherche linéaire peut être améliorée en premier à jeter tous les facteurs de 2. Qui peut être fait par simple décalage de bits, ou le comte de formation de zéro avec une belle fonction intrinsèque. C'est très rapide dans les deux cas. Ensuite, exécutez l'algorithme proposé par shg (qui s'exécute beaucoup plus rapidement maintenant que les puissances de deux ne sont pas présents), et de combiner les résultats avec toutes les puissances de deux (n'oubliez pas cette étape). Cela aide beaucoup pour les entrées qui ont beaucoup de formation de zéro, mais il aide même si ils ne le font pas, vous ne pas avoir à tester des diviseurs de plus, afin que la boucle devient la moitié du temps.
Jeter quelques constante des facteurs (mais plus grand que 2) peut également aider. Modulo une constante est presque certainement optimisé par le compilateur (ou si pas, vous pouvez le faire vous-même), mais plus important encore, cela signifie qu'il ya moins de diviseurs de la gauche à l'épreuve. N'oubliez pas de combiner ce facteur avec les diviseurs vous trouvez.
Vous pouvez également factoriser le nombre complètement (utilisez votre favori algorithme probablement Pollard Rho serait le mieux), puis l'imprimer tous les produits (sauf le vide et le plein de produits) des facteurs. Cela a une bonne chance de se retrouver en étant plus rapide pour les plus grosses entrées - Pollard Rho algorithme recherche des facteurs très rapidement par rapport à une simple recherche linéaire, il y a généralement moins de facteurs de diviseurs propres, et la dernière étape (l'énumération des produits) n'implique rapide des mathématiques (pas de divisions). La plupart du temps cela aide pour les nombres avec de petits facteurs qui Rho le plus rapide.
Code présenté dans l'une des réponses a un bug qui est difficile à voir au premier coup d'œil. Si sqrt(n) est valide diviseur; mais n n'est pas un carré parfait numéro,puis deux résultats sont omis.
E. g. Essayez
n = 15
, et de voir ce qui se passe;sqrt(15) = 3
, de sorte que la dernière valeur de la boucle while est 2. La prochaine instruction exécutéeif (i * i == n)
sera exécuté commeif(3 * 3 == 15)
. Donc 3 n'est pas répertorié comme un diviseur, aussi 5 a été manquée.La suite va traiter le cas général d'entiers positifs correctement.
Quand le nombre est impair, on peut même passer le même nombre.
Une légère improvisation dans le code accepté 🙂
Ici le code Java pour trouver les facteurs d'un nombre donné.
C'est ma nouvelle Version de C#. Grâce à Rndm c'est près de 50 fois plus rapide que mon premier essai.