Come si fa a generare una quantità definita dall'utente dei numeri primi?

StackOverflow https://stackoverflow.com/questions/2415033

  •  19-09-2019
  •  | 
  •  

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
È stato utile?

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));

copiato da codethinked.com

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top