Newsgroup: it.comp.java
Titolo: Errore

Scusate mi sapreste dire, perche qusto codice, in fase di esecuzione,
mi da come errore:Exception in thread "main"
java.lang.ArrayIndexOutOfBoundsException: 1000?
class trovaprimi
{
  final int MAX=1000;
  public int primi[]=new int[(MAX)];
  private  int evita[]=new int[(MAX)];
  public int num=0;
  private int k=0;
  public trovaprimi()
  {
    primi[0]=1;
    for (int i=2;i<=MAX;i++)
    {
     multipli(i);
    }
  }
 private void multipli(int n)
 {
   int prod=0;
   for(int i=2;i<=MAX;i++)
   {
     if (prod<MAX)
     {
      prod=n*i;
      if (prod <MAX)
      {
       evita[k]=prod;
       k++;
      }
     } else break;
    }
  esamina(n);
   }
   private void esamina(int n)
   {
     boolean contr;
     for (int i=0; i<=k;i++)
     {
       contr=(n!=evita[i]?false:true);
       if (contr=true)break;
     }
     if (contr=false)
      {
        primi[num]=n;
        num++;
      }
    }
  }
class NumPrimi
{
 public static void main (String args[])
  {
   int i;
    trovaprimi trova=new trovaprimi();
    for (i=0;i<=trova.num;i++)
    {
      System.out.println (trova.primi[i]);
    }
  }
}

 java.lang.ArrayIndexOutOfBoundsException: 1000?
Io vedo subito un MAX=1000 ed un ciclo for (int i=2;i<=MAX...)
Non č che dovevi fare solo <MAX?
Utilizza cmq lo stile di programmazione raccomandato (nomi, indentazione
etc), cosě ci troviamo meglio tutti ;)

        evita[k]=prod;
questa genera l'OutOfBounds
k puo' diventare > 1000
....
--
ac

Tu stai allocando un vettore di 1000 posizioni(da 0 a 999).
Quindi la locazione 1000 non esiste ed č lě che sfori.
Credo basti mettere i < MAX invece di i <=MAX
Megam ha scritto:


 Credo basti mettere i < MAX invece di i <=MAX
Ringrazio a tutti quelli che hanno risposto. Ho risolto il problema
aumentando il limite dell'array. Sono alle prime armi, grazie per la
pazienza.

 pazienza.
Si, certo. Ma hai coscienza di quanti elementi di "evita" ti servono?
Per come hai scritto il codice te ne dovrebbero servire E(MAX/n-1) ("E" 
sta per sommatoria per n da 2-->MAX-1)
E poi. Il codice potrebbe essere meno "involuto"
questo dovrebbe fare la stessa cosa:
public class TrovaPrimi {
   final int MAX=1000;
   public int primi[]=new int[(MAX)];
   public TrovaPrimi() {
     System.out.println(1);
     for (int i=2;i<MAX;i++){
        if(primi[i]==0){
            System.out.println(i);
            for(int ix=2;ix*i<MAX;ix++)
                primi[ix*i]=1;
        }
     }
}
...ed e' leggermente piu' veloce,sostanzialmente fa meno cicli e "primi" 
potrebbe essere trattato di tipo "byte".
--
ac

 potrebbe essere trattato di tipo "byte".
Sempre usando il tuo algoritmo come base, si puo' cmq fare meglio ad esempio 
evitando quello che palesemente non puo' essere primo (i numeri pari) si 
puo' con poca fatica ridurre la complessita' (questo lo si puo' fare in 
entrambi i cicli, partendo da 3 ed incrementando di due, facendo prima fuori 
dal loop il caso 2):
In realta' pero' se la memoria non e' un problema si puo' andare anche oltre 
(sempre seguendo il tuo algoritmo come schema, non ciclando i numeri pari ed 
usando un ulteriore array di appoggio):
public static class TrovaPrimi {
   private final byte NOT_CHECKED = 0;
   private final byte NOT_PRIME = 1;
   private final byte PRIME = 2;
   private final int max;
   private byte primeState[];
   private int primes[];
   private int primeIndex;
   public TrovaPrimi(final int max) {
      this.max = max;
      primeState = new byte[max];
      primes = new int[max];
   }
   public void calculate() {
      primeIndex = 0;
      primes[primeIndex++] = 1;
      primeState[1] = PRIME;
      primes[primeIndex++] = 2;
      primeState[2] = PRIME;
      for (int i = 3; i < max; i += 2) {
         if (primeState[i] == NOT_CHECKED) {
            primeState[i] = PRIME;
            primes[primeIndex++] = i;
         }
         for (int j = 2; j < primeIndex; ++j) {
            int result = primes[j] * i;
            if (result < max)
               primeState[result] = NOT_PRIME;
            else
               break;
         }
      }
   }
   public boolean isPrime(final int number) {
      if (number < 1)
         throw new RuntimeException("Number " + number + "is too small!");
      if (number >= max)
         throw new RuntimeException("Number " + number + "is too big!");
      return primeState[number] == PRIME;
   }
   public int[] getListOfPrimes() {
      return Arrays.copyOfRange(primes, 0, primeIndex);
   }
}
In questo caso usi due array, uno per sapere se il numero e' primo o meno, e 
l'altro per avere una comoda lista di primi (il ciclo interno ora invece di 
ciclare solo i numeri dispari, come consigliato sopra, fa meglio ancora e 
cicla solo i numeri primi).
Questo dovrebbe eseguire parecchio piu' veloce rispetto all'algoritmo 
originale e perssino rispetto alla versione leggermente modificata che evita 
i numeri pari in entrambi i cicli (questo togliendo il println da tutte le 
versioni, altrimenti le differenze non si vedono visto che la maggior parte 
del tempo e' speso facendo I/O).
Io poi preferirei cmq algoritmi che non usino cosi' tanta memoria, anche a 
scapito delle prestazioni, ad esempio con questi algoritmi non sarebbe 
possibile sulla maggior parte dei PC di oggi calcolare con MAX di 5 
miliardi, nemmeno se avessi tutto il tempo del mondo per aspettare il 
risultato, il problema e' che il mio PC ha solo 2GB di memoria! ;-)
Tommy

 Sempre usando il tuo algoritmo come base, si puo' cmq fare meglio ad esempio 
il suo algoritmo ;<)
Per quanto mi riguarda probabilmente *non* userei aree di *appoggio*.
Farei piu' *fatica* via codice ma e' questione di ed a che cosa si 
voglia dare priorita'.
Con le aree di appoggio e' dura calcolare i primi di 10^152 (oddio 
sarebbe dura anche via "solo" codice) ;<)
Io ho solo cercato di fargli *vedere* una possibile semplificazione del 
"suo" codice che mi sembrava, come ho gia' scritto, un po' "involuto".
Ovviamente,poiche' ti leggo sistematicamente, so che hai una certa 
dimestichezza con le ottimizzazioni di codice, quindi mi fido ;<) di 
cio' che scrivi "quasi" a scatola chiusa.
Ciao
[cut]
--
ac