Programme pour trouver les nombres premiers
Je veux trouver le premier nombre entre 0 et une variable de type long, mais je ne suis pas en mesure d'obtenir n'importe quelle sortie.
Le programme est
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication16
{
class Program
{
void prime_num(long num)
{
bool isPrime = true;
for (int i = 0; i <= num; i++)
{
for (int j = 2; j <= num; j++)
{
if (i != j && i % j == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
Console.WriteLine ( "Prime:" + i );
}
isPrime = true;
}
}
static void Main(string[] args)
{
Program p = new Program();
p.prime_num (999999999999999L);
Console.ReadLine();
}
}
}
Quelqu'un peut-il m'aider et trouver quelle est l'erreur possible dans le programme?
- Le modèle de projet a été utilisé pour créer ce projet.
- Les devoirs d'alerte !!
- Avez-vous des sortie si vous le mettez dans un petit nombre au départ, tels que 10?
- Probablement devoirs, rien de mal à cela tant que le demandeur a essayé de répondre aux devoirs problème et il est bloqué sur un problème spécifique (comme cela semble être le cas ici).
- Stocker: c'est le plus patological exemple que j'ai vu de ce problème :S
- Même si vous vous en tenez à l'algorithme naïf, au moins arrêter la recherche à la racine carrée.
- Combien de temps cette chose fait prendre? 999999999999999L est tout à fait un grand nombre?
- il prendra la durée de vie, même lorsqu'fixe que par les réponses ci-dessous, ni le but de générer tous ces nombres premiers expliqué. Si le but est en faisant la somme, de trouver la première occurrence de lacunes, les doubles, les triples, et ainsi de suite, alors la seule approche possible serait d'écrire un très efficace multi-processeur page-sectorielle version du Crible d'Eratosthène, qui devrait prendre un mois ou deux sur un modernes haut de gamme de l'ordinateur de bureau, mais pourrait être mis à l'échelle pour s'exécuter sur des centaines de milliers de cœurs d'un super-ordinateur pour exécuter en quelques secondes.
Vous devez vous connecter pour publier un commentaire.
Vous pouvez le faire plus rapidement à l'aide d'un presque optimale section de première instance de tamis dans une (longue) ligne comme ceci:
Le rapprochement formule pour le nombre de nombres premiers utilisée ici est
π(x) < 1.26 x /ln(x)
. Nous avons seulement besoin de tester par les nombres premiers ne sont pas plus grand quex = sqrt(num)
.Noter que le crible d'Eratosthène a beaucoup plus de temps d'exécution de la complexité de la section de première instance (devrait fonctionner beaucoup plus rapidement pour un plus grand
num
valeurs, lorsqu'elles sont correctement mises en œuvre).num
et, de même, la seconde devrait être de 2 ànum
, et laRemoveAll
ligne doit êtreresult.RemoveAll(i => i > index && i % index == 0);
result
est cueilli sur chaque étape; à l'aide deresult[index]
, avecindex = 0,1,2,3...
, progressivement, les tests et les résidus de laresult
liste par 2,3,5,7,11,... . Vous avez raison que les plages sont de mauvais pourtant, il me semble.RemoveAll()
ne peut pas le faire de façon optimale.result
. Les listes commencent à l'indice 0.Sqrt
de longueur totale - avec ma proposé de modifier, qui est. On pourrait dire alors, que c'est un presque optimale section de première instance de tamis. Le plus important est de limiter le nombre d'itérations à partirnum
PrimePi[Sqrt[num]]
.num
valeurs, ou augmente-t-elle?Essayez ceci:
num
limite supérieure dans la boucle interne; cette réponse changements au inefficace, mais pas fou,i
. Évidemment, l'objectif de ce programme est juste pour imprimer un flux régulier de primes, pas de print eux tous... Et le code d'origine n'ai pas l'impression tous en raison de la folle test1%2, 1%3, ... 1%(10^15-1)
qui étaient bien sûr tous les non-zéro, donc finalement c' aurait rapport de 1 en tant que premier. Une chose de plus: ce code ici n'rapport 0 et 1 comme les nombres premiers de si. 🙂i
devrait commencer à partir de 2 trop.j
permettrait d'atteindre 0 et finalement provoquer div par zéro dans1%j
. i7 core est un 100 gigaFLOPS puce, 100*10^9 , ce qui devrait arrivé en moins d'une seconde. Peut-être, en C#,int
s sont en 64 bits? Puis une course de 10^15 arriverait-il, en prenant environ 20 minutes...2 heures de temps, pouri=1
.-1
, belle prise! 🙂Vous avez uniquement besoin de vérifier impair de diviseurs jusqu'à la racine carrée de ce nombre. En d'autres termes, votre boucle interne doit commencer:
Vous pouvez également sortir de la fonction dès que vous trouvez le nombre n'est pas premier, vous n'avez pas besoin de vérifier plus de diviseurs (je vois que vous êtes déjà ce que!).
Cela ne fonctionnera que si le nombre est plus grand que deux.
Pas Sqrt
Vous pouvez éviter la Sqrt ensemble en conservant une somme en cours d'exécution. Par exemple:
C'est parce que la somme des chiffres 1+(3+5)+(7+9) vous donnera une séquence de petits carrés (1,9,25 etc). Et donc
j
représente la racine carrée desquare_sum
. Aussi longtemps quesquare_sum
est à moins dei
puisj
est inférieur à la racine carrée.Personnes ont mentionné un couple de blocs de construction vers faire cela efficacement, mais personne n'est vraiment mettre les morceaux ensemble. Le crible d'Eratosthène est un bon début, mais avec elle, vous serez à court de mémoire long avant d'atteindre la limite que vous avez définie. Cela ne veut pas dire que c'est inutile si -- quand vous faites votre boucle, ce qui compte vraiment pour vous sont les diviseurs premiers. En tant que tel, vous pouvez commencer par utiliser un tamis à créer une base de diviseurs premiers, puis utilisez les dans la boucle pour tester les nombres de la primauté.
Lorsque vous écrivez la boucle, cependant, vous avez vraiment ne voulez PAS que nous sqrt(i) dans la condition de la boucle, comme un couple de réponses ont suggéré. Vous et moi savons que la racine carrée est un "pur" de la fonction qui donne toujours la même réponse si on a les même paramètre d'entrée. Malheureusement, le compilateur ne sait PAS que, si utiliser quelque chose comme " <=Math.sqrt(x) " dans la condition de la boucle, il va re-calculer la racine carrée du nombre de chaque itération de la boucle.
Vous pouvez éviter qu'un couple de différentes manières. Vous pouvez pré-calculer la racine carrée avant la boucle, et d'utiliser le pré-calculé la valeur de la condition de la boucle, ou vous pouvez travailler dans l'autre sens, et le changement
i<Math.sqrt(x)
ài*i<x
. Personnellement, je l'avais pré-calculer la racine carrée si -- je pense que c'est plus clair et probablement un peu plus vite--mais qui dépend du nombre d'itérations de la boucle (lai*i
signifie qu'il est encore en train de faire une multiplication dans la boucle). Avec seulement quelques itérations,i*i
sera généralement plus rapide. Avec un nombre suffisant d'itérations, la perte dei*i
chaque itération, l'emporte sur le temps d'exécutionsqrt
une fois en dehors de la boucle.C'est probablement suffisante pour la taille de numéros que vous avez à traiter avec-un de 15 chiffres de la limite, la racine carrée est à 7 ou 8 chiffres, qui s'inscrit dans un assez raisonnable quantité de mémoire. D'autre part, si vous souhaitez traiter les nombres dans cette gamme, vous pouvez jeter un oeil à quelques-uns des plus sophistiqués premier vérification d'algorithmes, tels que Pollard ou de Brent, les algorithmes de. Ceux-ci sont plus complexes (c'est un euphémisme), mais un beaucoup plus rapide pour les grands nombres.
Il existe d'autres algorithmes pour encore plus de chiffres (le crible quadratique, général champ numéro de tamis) mais nous n'allons pas entrer dans eux pour le moment, ils sont beaucoup plus complexes, et vraiment utile pour traiter avec de très grands nombres (la GNFS commence à être utile dans les 100+ chiffres).
Première étape: écrire une extension de la méthode pour savoir si une entrée est le premier
2 étape: écrire la méthode qui vous permettra d'imprimer tous les nombres premiers entre 0 et le nombre d'entrée
isPrime
sera de retourtrue
pour les 0, 1, et pour tout nombre négatif. De sorte que la boucle à l'intérieur degetAllPrimes
devrait commencer à partir deint i = 2;
, au moins.return true;
devrait être la prochaine instruction après lafor
déclaration, il est bon maintenant (seulement le texte de l'indentation n'est pas droit). mais la fonctionisPrime
comme l'écrit, suppose2 <= number
. Dans d'autres cas, il ne fonctionnera pas correctement. Donc, partout où vous les utilisez, assurez-vous de tester un nombre plus grand que 1 avec. C'est un choix judicieux, puisque pas moins de 2 est un nombre premier, donc besoin de vérifier ces chiffres. Que signifie, il vous suffit de changer la valeur de départ pouri
dans la boucle degetAllPrimes
, pour commencer pas de0
, mais à partir de2
. Si non, votre programme affichera 0 et 1 comme des nombres premiers.number
dansisPrime
.C'est peut être juste mon avis, mais il y a une autre grave erreur dans votre programme (mise à part le premier numéro de la question, qui a été complètement répondu).
Comme le reste des intervenants, je suppose que c'est les devoirs, ce qui indique que vous souhaitez devenir développeur (sans doute).
Vous avez besoin d'apprendre à compartimenter votre code. Ce n'est pas quelque chose que vous aurez toujours besoin d'avoir à faire à un projet, mais il est bon de savoir comment le faire.
Votre méthode prime_num(long num) peut supporter un mieux, un nom plus descriptif. Et si c'est censé trouver tous les nombres premiers inférieurs à un nombre donné, elle doit retourner la liste. Cela rend plus facile de séparer votre écran et votre fonctionnalité.
Si il a simplement renvoyé une IList contenant des nombres premiers, vous pouvez les afficher dans votre fonction main (peut-être appeler un autre à l'extérieur de la fonction à peu les imprimer) ou de les utiliser dans d'autres calculs en bas de la ligne.
Donc ma meilleure recommandation pour vous de faire quelque chose comme ceci:
Même si vous finissez par travailler dans un endroit où speration comme ce n'est pas nécessaire, il est bon de savoir comment le faire.
EDIT_ADD: Si Ness est vrai que la question est juste à la sortie d'un flux continu de nombres premiers pour aussi longtemps que le programme est exécuté (en appuyant sur Pause/Pause pour mettre en pause et une touche pour démarrer à nouveau) sans beaucoup d'espoir de tous arriver à ce plafond, puis le code doit être écrit sans limite d'argument et un contrôle de portée de la "vrai" pour la première " je " pour la boucle. D'autre part, si la question voulait réellement imprimer les nombres premiers jusqu'à une limite, alors le code suivant va faire le travail beaucoup plus efficacement au moyen de la Division de première instance uniquement pour les nombres impairs, avec l'avantage qu'il n'utilise pas de mémoire du tout (il pourrait également être converti en une boucle continue comme ci-dessus):
D'abord, la question de code ne produit aucune sortie à cause de ce son en boucle les variables sont des nombres entiers et la limite de l'essai est un énorme entier long, ce qui signifie qu'il est impossible pour la boucle de façon à atteindre la limite de produire une boucle interne ÉDITÉ: lequel la variable "j' boucle de retour autour de nombres négatifs; lorsque le 'j' variable revient environ à -1, l'essai numéro échoue le test d'amorçage, parce que tous les nombres sont divisibles par -1 END_EDIT. Même si cela a été corrigée, la question de code produit très lente sortie car il est lié à faire en 64 bits divisions de très grandes quantités de nombres composés (tous les numéros plus le bizarre composites) par l'ensemble de la gamme des nombres jusqu'à que nombre supérieur de dix élevé à la seizième puissance pour chaque premier qui il peut éventuellement produire. Le code ci-dessus fonctionne, car elle limite le calcul uniquement les nombres impairs et seulement modulo divisions jusqu'à la racine carrée du nombre actuel d'être testé.
Cela prend une heure pour afficher les nombres premiers jusqu'à un milliard de dollars, de sorte que l'on peut imaginer la quantité de temps qu'il faudrait pour afficher tous les nombres premiers inférieurs à dix mille milliards de dollars (10 élevé à la seizième puissance), d'autant que le calcul devient plus lent, avec une augmentation de la distance. END_EDIT_ADD
Bien que l'un liner (genre de) réponse par @SLaks à l'aide de Linq fonctionnement, il n'est pas vraiment le Crible d'Eratosthène que c'est juste une unoptimised version de Division De Première Instance, unoptimised en ce qu'elle n'élimine pas l'impair de nombres premiers, ne démarre pas à la place du trouvé de la base de premier, et de ne pas arrêter l'abattage pour la base de nombres premiers plus grand que la racine carrée du nombre supérieur à tamis. Il est également très lent en raison de multiples imbriqués l'énumération des opérations.
Il est en fait un abus de Linq méthode des Agrégats et de ne pas utiliser efficacement la première des deux Linq Gamme de produit. Il peut devenir un optimisée de la Division de première instance avec moins dénombrement de frais généraux comme suit:
qui s'exécute plusieurs fois plus rapide que la SLaks réponse. Cependant, il est encore lent et de mémoire intensive en raison de la Liste de la génération et de la multiplicité des énumérations ainsi que les multiples fracture (implicite par le modulo) opérations.
La suite Crible d'Eratosthène mise en œuvre s'exécute environ 30 fois plus rapide et prend beaucoup moins de mémoire qu'il utilise seulement un peu de la représentation par nombre tamisé et les limites de son énumération à la finale itérateur sortie de la séquence, comme bien d'avoir des optimisations de traiter seulement bizarre composites, et seulement l'abattage de la carrés de la base de nombres premiers pour la base de nombres premiers inférieurs à la racine carrée du nombre maximal, comme suit:
Le code ci-dessus calcule tous les nombres premiers inférieurs à dix millions de gamme dans environ 77 millisecondes sur un processeur Intel i7-2700K (3.5 GHz).
L'une des deux méthodes statiques peuvent être appelés et testé avec les instructions à l'aide et à la statique Principale méthode comme suit:
qui affichera le nombre de nombres premiers dans l'ordre jusqu'à la limite, le dernier premier trouvé, et le temps consacré à l'énumération de loin.
EDIT_ADD: Toutefois, afin de produire une énumération du nombre de nombres premiers inférieurs à dix mille milliards de dollars (dix à la seizième puissance) que la question demande, une segmentation paginée approche de l'utilisation de multi-core de traitement est nécessaire, mais même avec le C++ et le très hautement optimisé PrimeSieve, cela nécessiterait quelque chose de plus de 400 heures à produire le nombre de nombres premiers trouvés, et des dizaines de fois que le long de tous les énumérer ainsi, sur une année pour faire ce que la question se pose. Faire à l'aide de l'onu-optimisé Division de première instance de l'algorithme tenté, il va prendre super éons et un très très long moment, même à l'aide d'un optimisée de la section de première instance de l'algorithme, comme dans quelque chose comme dix à la deux millionième années de pouvoir (c'est deux millions de zéros ans!!!!!).
Il n'est pas étonnant que son ordinateur de bureau à juste assis et a décroché quand il a essayé!!!! S'il avait essayé une petite plage comme un million de dollars, il aurait constaté qu'il prend dans la gamme de secondes de mise en œuvre.
Les solutions que je poste ici ne pas le couper plus que même le dernier Crible d'Eratosthène on aura besoin d'environ 640 Téraoctets de mémoire pour cette gamme.
C'est pourquoi seule une page d'approche segmentée comme celui de PrimeSieve peut gérer ce genre de problème pour la plage comme spécifié à tous, et même ce qui nécessite un temps très long, comme dans les semaines à ans, sauf si l'on a accès à un super-ordinateur avec des centaines de milliers de cœurs. END_EDIT_ADD
Sent plus de devoirs. Mon très très vieux calculatrice graphique a un est le premier programme de ce genre. Technnically l'intérieur devision vérification de la boucle n'a besoin que de l'i^(1/2). Avez-vous besoin de trouver "toutes" les nombres premiers entre 0 et L ? L'autre problème majeur est que vos variables de boucle sont "int", tandis que vos données d'entrée est "long", cela va provoquer un dépassement de capacité de prise de vos boucles ne parviennent pas à exécuter une seule fois. Fixer les variables de boucle.
Une ligne de code en C# :-
La Crible d'Eratosthène réponse ci-dessus n'est pas tout à fait correct. Comme l'a écrit elle permet de trouver tous les nombres premiers entre 1 et 1000000. Pour trouver tous les nombres premiers entre 1 et num utilisation:
La semence de le total devrait être de l'ordre de 1 à num depuis cette liste contiendra la liste finale des nombres premiers. Le
Enumerable.Range(1, Convert.ToInt32(Math.Floor(Math.Sqrt(num))))
est le nombre de fois que la graine est purgé.ExchangeCore Forums avoir une bonne console application énumérés qui ressemble à écrire trouvé les nombres premiers dans un fichier, il semble que vous pouvez également utiliser ce même fichier en tant que point de départ de sorte que vous n'avez pas à redémarrer trouver des nombres premiers de 2 et ils fournissent le téléchargement de ce fichier avec tous trouvé les nombres premiers jusqu'à 100 millions de dollars de sorte qu'il serait un bon début.
L'algorithme sur la page prend également quelques raccourcis (numéros impairs et vérifie seulement jusqu'à la racine carré) ce qui le rend extrêmement efficace et il vous permettra de calculer les nombres longs.
c'est donc essentiellement juste deux fautes de frappe, l'un, le plus malheureux,
for (int j = 2; j <= num; j++)
qui est la raison pour la improductive l'essai de1%2,1%3 ... 1%(10^15-1)
qui se passe pour très longtemps donc que l'OP n'a pas l'obtenir "sortie". Il aurait étéj < i;
à la place. L'autre mineure, en comparaison, est quei
devrait commencer à partir de 2, pas de 0:Sûrement, il ne peut pas être raisonnablement attendu d'un console impression de 28 milliards de nombres premiers, ou alors pour être achevée dans un délai raisonnable-cadre. Donc, l'intention originale du problème était évidemment pour imprimer un flux continu de nombres premiers, indéfiniment. Par conséquent, toutes les solutions que propose l'utilisation simple de la crible d'Eratosthène sont totalement sans fondement ici, parce que simple crible d'Eratosthène est bornée à une limite doit être définie à l'avance.
Ce qui pourrait fonctionner ici est l'optimisation de la division de première instance qui permettrait d'économiser des primes comme il les trouve, et de test sur les nombres premiers, et pas seulement tous les numéros ci-dessous le candidat.
Deuxième alternative, avec beaucoup plus de complexité (c'est à dire beaucoup plus rapide) est d'utiliser un segmenté crible d'Eratosthène. Qui est progressive et sans limite.
Ces deux plans d'utilisation double-mise en scène de nombres premiers: l'une serait de produire et d'enregistrer les premiers, à être utilisé par l'autre étape dans l'essai (ou tamisage), bien au-dessus de la limite de la première étape (en dessous de sa place de cours - la prolongation automatique de la première étape, la deuxième étape serait d'aller plus loin et plus haut).
Pour être tout à fait franc, certaines des solutions proposées sont vraiment très lent, et, par conséquent, sont de mauvais conseils. Pour le test d'un seul numéro pour être le premier vous avez besoin de quelques divisant/opérateur modulo, mais pour le calcul d'une plage que vous n'avez pas à.
Fondamentalement, il suffit d'exclure les nombres qui sont des multiples de plus tôt trouvé les nombres premiers, comme le sont, par définition, pas de nombres premiers eux-mêmes.
Je ne vais pas donner la pleine mise en œuvre, que ce serait facile, c'est l'approche en pseudo code. (Sur ma machine, la mise en œuvre effective calcule tous les nombres premiers dans un Système.Int32 (2 milliards) dans un délai de 8 secondes.
La solution nécessite une bonne compréhension des opérations bit à bit. Mais il des moyens, et des moyens plus rapides. Vous pouvez également sûr le résultat le résultat sur le disque, si vous en avez besoin pour une utilisation ultérieure. Le résultat de 17 * 10^9 numéros peuvent être safed avec 1 GO, et le calcul de l'ensemble des résultats prend environ 2 minutes max.
Je sais que c'est calme vieille question, mais après avoir lu ici:
Crible d'Eratosthène Wiki
C'est la façon dont je l'ai écrit à partir de la compréhension de l'algorithme:
Dans la première boucle, on remplit le tableau de booléens avec vrai.
Deuxième boucle for va commencer à partir de 2 depuis le 1 n'est pas un nombre premier et va vérifier si le premier nombre est toujours pas changé, et ensuite attribuer de la valeur false à l'indice de j.
dernière boucle nous avons juste l'impression quand il est premier.
Très similaire à partir d'un exercice pour mettre en œuvre Crible d'Eratosthène en C#:
Premier Helper très rapide calcul
U peut utiliser la normale nombre premier concept doit seulement deux facteurs (l'un et de lui-même).
Afin de faire ceci,de façon facile
Cette solution affiche tous les nombres premiers entre 0 et 100.
C'est le moyen le plus rapide pour calculer les nombres premiers en C#.
PrimeNumber
avec un même nombre, par exemplePrimeNumber(1000000000000000000)
, il calcule la racine carrée, et faire la boucle, même si elle sait tout de suite ce n'est pas le premier! (n.b. 1000000000000000000 est de moins deInt64.MaxValue
). Il va ensuite exécuter la boucle sur les nombres impairs à partir de 3 jusqu'à la racine carrée, 1000000000 - ce qui est très inefficace et inutile, puisque nous savons déjà ce n'est pas le premier.Il y a quelques très optimale des moyens à mettre en œuvre l'algorithme. Mais si vous ne savez pas beaucoup au sujet de maths et il vous suffit de suivre la définition du premier que de l'exigence:
un nombre qui n'est divisible que par 1 et par lui-même (et rien d'autre), voici une technique simple pour la compréhension du code pour les nombres positifs.
Puisque chaque nombre est divisible par 1 et par lui-même, nous avons commencer à vérifier à partir de 2 jusqu'à ce que le nombre immédiatement avant de lui-même. C'est le raisonnement de base.
Vous pouvez le faire aussi ceci: