2013-04-20 8 views
6

La mia domanda è legata al seguente codice:Usando la logica all'interno di un'istruzione switch

public static void main(String[] args) { 

    // Find Prime Numbers from 0 to 100 
    int i; 
    for (i=2; i <= 100; i++) { 
     int j = 2; 
     boolean iPrime = true; 

     //The following line gives incorrect results, but should execute faster 
     // while ((iPrime = true) && (j < (i/2 + 1))) { 
     //The following line gives correct results but performs un-necessary operations 
     //by continuing to calculate after the number is found to be "not prime" 
     while (j < (i/2 + 1)) { 

      j++; 
      if ((i % j) == 0) { 
       iPrime = false; 
       //System.out.println(j + " is a factor of " + i); 
      } 
     } 
     if (iPrime) { 
      System.out.println(i + " is a prime number!"); 
     } 
    } 
} 

Ora, come ho commentato nel codice, quello che sto cercando di realizzare è un esecuzione più veloce del mio programma eseguendo il ciclo 'while' solo quando iPrime = true. Il 50% dei numeri è divisibile per 2 e quindi una volta stabilito questo i calcoli possono fermarsi.

sto facendo questo progetto come parte di un principiante 'esempio' da un libro, io in realtà sto cercando di calcolare fino a 1000000 nel minor tempo possibile solo per il mio "credito extra" ...

ho letto che il "corto circuito 'e' operatore" & & rileva solo la seconda metà della dichiarazione se la prima metà è vero, se è falso, i due non vengono valutati contro l'altro (CPU risparmio)

E uscirà anche il ciclo, che salverà ancora più CPU ...

Ma per som La ragione, non funziona correttamente! Ho messo più istruzioni System.out.println() in tutto, elencando cosa sia 'iPrime' - e l'output è strano ... Commuta e spegne iPrime e valuta ogni numero, che non riesco a capire.

+0

Grazie per l'aiuto di tutti! E 'stato così ovvio una volta che ho avuto le tue risposte, e il setaccio di Eratostene sarebbe davvero un algoritmo decisamente migliore! Posso solo scegliere una risposta ma siete stati tutti altrettanto utili, grazie! – JBainesy

risposta

7

if((iPrime = true) && ...) deve essere if((iPrime) && ...).

Facendo isPrime = true allora siete assegnazione vera a isPrime e non confrontando suo valore al true.

Si potrebbe anche voler vedere this per capire meglio ciò che accade nel codice:

In fase di esecuzione, il risultato dell'espressione di assegnazione è il valore della variabile dopo si è verificato l'assegnazione. Il risultato di un'espressione di assegnazione non è di per sé una variabile.

Così, quando si utilizza l'operatore di = invece di == (che viene rimosso quando si confronta qualcosa da true - invece di scrivere if(someBoolean == true) basta scrivere if(someBoolean)), si sta effettivamente soddisfare la condizione, sempre!

+1

SÌ! Adesso è così chiaro! Ricordo di aver pensato quando ho letto per la prima volta gli operatori =/== che mi avrebbero ingannato! Apprezzo l'aiuto, d'ora in poi starò attento a quella trappola! – JBainesy

+0

Sono contento che ci abbia aiutato, buona fortuna :) – Maroun

4

Basta cambiare = in ==, cioè, cambiare

while ((iPrime = true) && (j < (i/2 + 1))) 

in

while ((iPrime == true) && (j < (i/2 + 1))) 

Un codice completo con la migliore prestazione

public static void main(String[] args) { 
    // Find Prime Numbers from 0 to 100 
    System.out.println(2 + " is a prime number!"); 
    for (int i = 3; i <= 100; i += 2) { 
     boolean isPrime = true; 
     for (int j = 3; j * j <= i; j += 2) { 
      if ((i % j) == 0) { 
       isPrime = false; 
       break; 
      } 
     } 
     if (isPrime) { 
      System.out.println(i + " is a prime number!"); 
     } 
    } 
} 

Il metodo più veloce che posso pensare è Sieve of Eratosthenes.

+0

Oppure 'while (iPrime && (j <(i/2 + 1))' –

+1

'someBoolean == true'? Veramente? –

+0

@AchintyaJha quindi postare '1 == 1' è buono, giusto? –

1

johnchen902/Maroun Maroun risolvono il problema; Inoltre, l'ottimizzazione è possibile eseguire è

System.out.println("2 is a prime number!"); // the for loop won't detect 2 anymore 
for (i=3; i <= 100; i+=2) { 

Inoltre, invece di eseguire l'operatore modulo su un numero con tutti i numeri dispari precedenti per vedere se è primo, è possibile eseguire l'operatore modulo su un numero con tutti i numeri primi precedenti per vedere se è primo - per esempio, memorizza i numeri primi che trovi in ​​un ArrayList e itera l'elenco nel test principale.

E per un (spazio efficiente ma meno) algoritmo molto efficiente della CPU, utilizzare la Sieve of Eratosthenes

1

In primo luogo sulla gestione del codice che ho trovato che mostra 4 come un numero primo che non è corretto. La ragione è la posizione della tua linea j ++. Si dovrebbe cambiare il ciclo while come:

while (j < (i/2 + 1)) { 
       if ((i % j) == 0) { 
        iPrime = false; 

        //System.out.println(j + " is a factor of " + i); 
        break; 
       } 
       j++; 
      } 

Passando alla seconda parte, si vuole evitare di calcolo in più quando si è accertato che il numero non è primo. Puoi usare l'istruzione break per questo come nel codice sopra.

La parte commentata non funziona perché si dispone di un incarico anziché di un confronto di uguaglianza.

Problemi correlati