Come si fa a generare una quantità definita dall'utente dei numeri primi?
Domanda
Sto cercando di generare numeri primi in base all'input dell'utente. Questo è ciò che ho finora, ma io proprio non riesco a capirlo:
Console.Write("Please enter the number of prime numbers you would like to see:");
int numberOfPrimes = Convert.ToInt32(Console.ReadLine());
for (int x = 0; x < numberOfPrimes; x++)
{
for (int a = 2; a <= x ; ++a)
{
bool prime = true;
for (int b = 2; b < a; ++b)
{
if (a % b == 0)
{
prime = false;
}//end if
}//end double nested for
if (prime == true)
{
Console.WriteLine(a);
}//end if
}//end nested for
}//end for
Soluzione
Si dovrebbe essere in grado di vedere il motivo per cui i risultati sono sbagliati abbastanza facilmente se si guarda a vostre strutture ad anello. Passo attraverso di loro a mano (non ci vorrà molto).
Il motivo per cui si stanno ottenendo i risultati attuali è che non ogni iterazione del ciclo esterno (x < numberOfPrimes
) produce un risultato - si salta un bel paio di iterazioni a causa del modo in cui il ciclo interno è strutturato
Quello che si ha realmente bisogno di fare è ristrutturare i cicli interni. Il tuo ciclo più interno funziona bene, e dovrebbe rilevare eventuali numeri primi. Il tuo secondo ciclo, tuttavia, dovrebbe provare solo i numeri che non sono ancora stati testati. Inoltre, dovrebbe smettere di loop una volta a trovare un numero primo.
Altri suggerimenti
Si dovrebbe strutturare il codice migliore, è davvero disordinato il modo di fare ora. Avere un metodo IsPrime(int x)
che restituisce vero se x
è primo e false altrimenti.
Quindi, per generare numeri primi numberOfPrimes
, si può fare qualcosa di simile:
for ( int primeCount = 0, currentPrime = 2; primeCount < numberOfPrimes; ++currentPrime )
if ( IsPrime(currentPrime) )
{
// do whatever you want with currentPrime, like print it
++primeCount;
}
In alternativa, utilizzare il Crivello di Eratostene , che è un metodo molto più veloce.
Per capire se un numero x
è primo o no, provare tutti i suoi fattori tra 2
e Sqrt(x)
. Perché Sqrt(x)
solo? Perché se a*b = x
, quindi x / b = a
e x / a = b
, Così si avrebbe controllare tutto due volte, e anche controllare le cose non si deve se si è andato fino a x / 2
o addirittura x
.
Quindi, una cosa del genere, se si desidera utilizzare la funzione IsPrime(x)
:
// i <= Sqrt(x) <=> i * i <= x
for ( int i = 2; i * i <= x; ++i )
if ( x % i == 0 )
return false;
return true;
Ma vi consiglio di utilizzare il crivello di Eratostene, in quanto è molto più veloce. È inoltre possibile ottimizzare le cose in modo da non controllare i numeri pari, dal momento che un numero non è mai il primo, ad eccezione di 2 (sia nel setaccio e il metodo ingenuo). Trattare x = 2 come un caso limite e quindi avviare il controllo ogni altro numero (3, 5, 7, 9, 11 ecc.)
Quello che state cercando è chiamato "Crivello di Eratostene." Come io non sono nel fare i compiti a casa della gente, questo è l'unico indizio che sto per darvi. L'algoritmo è facilmente reperibile su internet.
Il numero primo successivo (x) - è il numero che cant essere diviso per tutti i primi s, che s <= sqrt (x). Così si può utilizzare la funzione come
public bool CheckAndAddPrime(int number,List<int> primes)
{
var sqrt = Math.Sqrt(number);
foreach(var prime in primes)
{
if(prime>sqrt) break;
if(number % prime == 0) return false;
}
primes.Add(number);
return true;
}
E di quanto si può ottenere numeri primi come
var primes = new List<int>();
Enumerable.Range(2,int.MaxValue).Where(x => x.CheckAndAddPrime(x,primes)).Take(YouCountOfPrimes);
var primes = Enumerable.Range(1, numberOfPrimes )
.Where(x => x != 1 &&
!Enumerable.Range2, (int)Math.Sqrt(x)).Any(y => x != y && x % y == 0));
static void Main(string[] args)
{
foreach (int no in get_first_k_primes(10))
{
Console.Write(" "+no.ToString() );
}
}
public static List<int> get_first_k_primes(int k)
{
var primes = new List<int>();
primes.Add(2);
int i = 3;
while(primes.Count < k)
{
if(is_prime(i))
primes.Add(i);
i += 2;
}
return primes;
}
public static bool is_prime(int n)
{
if (n % 2 == 0 && n != 2) return false;
int m = (int)Math.Ceiling(Math.Sqrt(n));
for (int i = 3; i < m; i += 2)
{
if (n % i == 0) return false;
}
return true;
}
1. Rinominare le variabili.
In primo luogo, se questo è compito otterrete brutti voti (se il tuo insegnante è degno di questo nome) perché avete i nomi delle variabili senza senso (sì, anche numberOfPrimes
è sbagliato e deve essere denominato requiredNumberOfPrimes
. Quando vedo questa variabile chiedo io 'è questo il numero che vuole, o quante ha trovato?').
In secondo luogo, vi aiuterà a capire dove si sta andando male. Le variabili devono essere logicamente denominati in base a ciò che rappresentano. Se non è possibile spiegare che cosa le variabili rappresentano (ad esempio a & b) allora probabilmente non può spiegare cosa si sta facendo con loro.
2. Guardate i vostri cicli.
for (int x = 0; x < numberOfPrimes; x++)
La struttura di un ciclo for è (initialise; 'should I continue?'; 'each loop do this')
. Pertanto nel vostro ciclo
- Si sta continuando fino a quando x è uguale o grande rispetto
numberOfPrimes
*. - Ogni volta che si passa attraverso il ciclo si sta aggiungendo 1 al
x
.
Sei sicuro che questo è ciò che si vuole fare? x
sembra rappresentare il numero di primi che avete trovato. Allora perché non incrementarlo quando si trova un primo, piuttosto che quando si avvia un ciclo?
for (int a = 2; a <= x ; ++a)
for (int b = 2; b < a; ++b)
Siete alla ricerca ad ogni numero intero compreso tra 2 e x
, inclusiva. E per ciascuno di questi numeri interi a
, si sta cercando in ogni numero intero compreso tra a
e 2 compreso. Che cosa hai intenzione di fare con questi numeri interi?
Ogni volta che si esegue un ciclo attraverso il vostro livello superiore loop (il ciclo x
), che si sta per avviare il ciclo a
da zero, e ogni volta che si esegue un ciclo attraverso il vostro ciclo a
si inizierà il ciclo b
da zero.
Quindi, se x
è 10, si esegue attraverso una sola volta (a = 2), quindi si esegue attraverso un nuovo (a = 2, a = 3), quindi si esegue attraverso un nuovo (a = 2, a = 3 , a = 4), quindi ...
3. Raccogliere i risultati piuttosto che la scrittura della console.
var primes = new List<int>();
E 'così facile. Quando si trova un numero primo, primes.Add(a);
. Poi si sa quanti numeri primi avete trovato (primes.Count
), è possibile utilizzare l'elenco dei numeri primi di determinare in modo efficiente il prossimo primo, ed è possibile utilizzare l'elenco in seguito, se necessario.
Una volta che si vuole ricevere ithe spire magnetiche risolto, si hanno solo per verificare la presenza di b