Fehlersuche ...

Private Void

Aktives Mitglied
Ich bräuchte Hilfe bei folgendem Problem:

Beim folgenden Programmcode gibt Eclipse mir jene Fehlermeldung aus:
Code:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 142, Size: 142
	at java.util.ArrayList.RangeCheck(Unknown Source)
	at java.util.ArrayList.remove(Unknown Source)
	at Primzahlen.entfernen(Primzahlen.java:63)
	at Primzahlen.ergebnis(Primzahlen.java:58)
	at Primzahlen.nenner(Primzahlen.java:53)
	at Primzahlen.primzahlenGenerieren(Primzahlen.java:48)
	at Primzahlen.main(Primzahlen.java:19)

Ich weiß einfach nicht, was ich dagegen tun kann. Schaut also bitte mal nach, was ich hier falsch gemacht hab.

Java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.Timer;

public class Primzahlen{
	private int a = 5000; // Obere Grenze für die Berechnung
	private Timer timer;
	private int sec=0,min=0,hour=0,i,ii,j,k;
	private long z=0,x=0,ex=(long)(Math.pow(2, 63)-1);
	private ArrayList<Integer> al=new ArrayList<Integer>();
	
	public static void main(String[] args) throws IOException {
		Primzahlen pz = new Primzahlen();
		pz.zeit();
		pz.primzahlenGenerieren();
		pz.schreiben();
	}
	
	/** Der Timer ist dafür da, am Ende anzuzeigen wie lange es gedauert hat,
	* die Primzahlen zu berechnen (kommt bei größeren Zielwerten zum Tragen)*/
	private void zeit() throws IOException{
		timer = new Timer(1000, new ActionListener() {
        		public void actionPerformed(ActionEvent e) {
            			sec++;
                		if(sec==60){
                			sec=0;
                			min++;
                		}
               			 if(min==60){
                			min=0;
                			hour++;
            			}   }	});
		timer.start();
	}

	/* Die Vorgehensweise ist, dass Nicht-Primzahlen aus der ArrayList gelöscht werden */
	private void primzahlenGenerieren() throws IOException{
		for (int b = 1; b <= a; b+=2) {
			al.add(b);
		}
		al.add(1, 2);
		for (i = 1; i < al.size(); i++) {
			ii = al.get(i);
			nenner();
	}	}
	
	private void nenner(){
		for (j = 1; j < (int)(ii/2); j++) {
			ergebnis();
	}	}
	
	private void ergebnis(){
		for (k = 1; k < (int)(ii/2); k++) {
			entfernen();
	}	}
	
	private void entfernen(){
		if((float) ii/j==k){
			al.remove(i);
		}

	...

Der Code geht hier noch weiter, ist aber glaub ich unrelevant für das Problem
 

nrg

Top Contributor
al.remove(i-1); ?

darauf lässt mich zumindest "Index: 142, Size: 142" schließen. Ausser es ist Zufall
 

Michael...

Top Contributor
Nein i ist ja nach der Schleife genau al.size() - das ist ja das Kriterium solange i<al.size()

Ansonsten finde ich diese Vorgehensweise mit eine globalen Parameter eher ungeschickt.
 

Private Void

Aktives Mitglied
@nrg: ich hab die 1 einfach auch als Primzahl aufgefasst, also wäre dann die 2 die zweite!

Und ich weiß, dass der Index von Arrays bei 0 anfängt.
 
Zuletzt bearbeitet:

nrg

Top Contributor
ok. und al.remove(i-1); brachte nicht den gewünschten erfolg? wirft bei mir schonmal keine exception. den inhalt müsstest halt du mal prüfen. ich sag mal dazu, dass ich mich mit deinem code jetzt nich tiefer beschäftigt habe. finde nämlich die globalen parameter auch nicht so prickelnd :)
 
G

Gast2

Gast
Die Exception sagt doch alles deine Liste hat 142 Elemente von 0-141. Dann kannst du natürlich nicht auf index 142 zugreifen, weil das gibt es nicht. Also die Schleife richtig machen im notfall debugen dann siehst es am besten ^^...
 

Private Void

Aktives Mitglied
zwischen al.remove(i) und al.remove(i-1) war von der folge her kein Unterschied!
Ich hab den Fehler jetzt gefunden:
[java=61]
private void entfernen(){
if((float) ii/j==k && al.contains(ii)){
al.remove(i);
i--; // Das hier, weil nach dem Löschen eines Werts in der ersten Schleife sonst der nächste Wert der ArrayList übersprungen wird
}

...
[/code]
Wenn ich dieses 'contains' einfüge, funktionierts.

Da die Parameter alle in mehreren Methoden verwendet werden, hab ich das eben mit globalen Parametern gelöst.
Wie würde es euch besser gefallen, und warum?
 
Zuletzt bearbeitet:

Michael...

Top Contributor
Zunächst mal könnte man sprechende Varialblennamen verwenden.
Dann könnte man sich überlegen, ob die Zerlegung in soviele Methode überhaupt sinnvoll ist, da die Methoden nur eine weitere Methode in einer Schleife aufrufen.

Ausserdem kann man sich den Timer schenken.
Einfach vor dem Start die Systemzeit in einer Variablen speichern und am Ende den Inhalt der Varialben von der aktuellen Systemzeit abziehen und schon hat man die Dauer.
 

nrg

Top Contributor
Als Beispiel, wie ich es gemacht hätte:

Java:
import java.io.*;

public class Primzahlen {
	
	private double time;
	private boolean[] prims;

	public Primzahlen(int a) {
		prims = new boolean[a];
	}
	public double getTime() {
		return time;
	}
	public int getLength() {
		return prims.length;
	}
	public void primzahlenGenerieren() {
		time = (double)System.nanoTime();
		for (int i = 2; i < prims.length; i++)
			prims[i] = true;
		for (int i = 2; i < 10; i++){
			for (int j = i*2; j < prims.length; j+=i){
				prims[j] = false;
			}
		}
		time = (double)(System.nanoTime() - time) / 1000000;
	}
	public void schreiben() {
		for (int i = 0; i < prims.length; i++)
			if (prims[i]) System.out.println(i);
	}
	public static void main(String[] args) throws IOException {
		BufferedReader bisr = new BufferedReader ( new InputStreamReader (System.in));
		int input = 0;
		while (true) {
			System.out.print("Geben Sie das Maximum an> ");
			try {
				input = Integer.parseInt(bisr.readLine());
				break;
			} catch (NumberFormatException nfe) {
				System.out.println("Falsche Eingabe. Bitte Wiederholen! JavaFehler: " + nfe.getMessage());
			}
		}
		Primzahlen pz = new Primzahlen(input);
		pz.primzahlenGenerieren();
		pz.schreiben();
		System.out.println("Der Prozess für ein Maximum von " + pz.getLength() + " dauerte " + pz.getTime() + " ms");
	}
}

für max = 1000000:
Der Prozess für ein Maximum von 1000000 dauerte 5.847861 ms


lass das mal bei deinem Algo durchlaufen (für 1mio). du löscht dann ca eine halbe millionen Mal in der Mitte einen wert! Dazu solltest du schonmal eine LinkedList nehmen...

edit: Der Prozess für ein Maximum von 100000000 dauerte 649.717765 ms
die Zahl würde ich bei deinem Prog gerne mal sehen :D
 
Zuletzt bearbeitet:

Private Void

Aktives Mitglied
Man lernt eben nie aus :rtfm:, vor allem wenn man mit Java erst angefangen hat!
Thx für die Hilfe :toll:

Für 1.000.000 hätte mein Programm wahrscheinlich Tage gebraucht


Edit: Ich hab's mal so abgeändert, dass es die Zahlen in eine Textdatei schreibt. Diese Datei ist bei der Obergrenze 100.000.000 stolze 204.465 KB, also 199 MB groß (braucht 662 ms zur Berechnung)
 
Zuletzt bearbeitet:

Ähnliche Java Themen

Neue Themen


Oben