Java Mehrere Bugs in Programm

runagrog

Commander
Registriert
März 2012
Beiträge
2.095
Hallo Community, ich habe mich heute mal drangemacht, ein Programm zur Berechnung und von Primzahlen zur Übung zu erweitern, und zwar um eine kleine Dokumentation und Funktionen, mit denen man den Bereich, in dem Primzahlen berechnet werden, bestimmt. Die Dokumentation ist noch nicht abrufbar, und ein paar (nebensächlichere) Methoden wurden noch nicht geschrieben, aber sonst sollte das Programm stehen. ABER:
1. Wenn ich mithilfe der Befehle einen Bereich auswähle (bspw. 0 - 700) (also mit dem Befehl primes 700), zieht die Bremse nicht und scheinbar wird die Methode, die bis zum Sanktnimmerleinstag Primzahlen berechnet, ausgeführt. Merkwürdigerweise funktionieren sowohl primes 699 und primes 749, aber es scheint ein paar Bereiche zu geben, die mein Programm nicht mag. Ich habe bisher den Bereich um 300 aufwärts, 430 und 700 aufwärts gefunden. Was geht da falsch?
2. Wenn ich beispielsweise primes 100 eingebe, ist soweit alles richtig, aber 101 wird ebenfalls zu den Primzahlen von 0 - 100 (der sollte es jedenfalls sein) gezählt und als Ergebnis ausgegeben. Bei primes 200 wird 211 noch dazugezählt, und bei Primes 402 noch die 409. Es wird scheinbar immer noch die nächste Primzahl mit angegeben, die außerhalb des Bereichs liegt.
Hier wären die wahrscheinlich interessantesten Teile des Quelltexts:
Code:
static String Usereingabe = new String();
    static String temp = new String();
    static StringBuffer zahl1 = new StringBuffer();
    static StringBuffer zahl2 = new StringBuffer();
    static long num1, num2;
    public static void primes() {
    long numtotest = 1;
    long numtestdiv = 2;
    while(true) {
    if(numtotest == 1) {
    numtotest++;
    continue;
    }
    while(numtestdiv < numtotest) {
    if ((numtotest % numtestdiv) == 0 || numtotest == 1) {
    numtotest++; numtestdiv = 2; continue;
    } else {
    numtestdiv++;
    }
    }
    System.out.print(numtotest + " ");
    numtotest++; numtestdiv = 2;
    }
    }
    public static void primes1() {
    long numtotest = 1;
    long numtestdiv = 2;
    while(numtotest <= num1) {
    if(numtotest == 1) {
        numtotest++;
        continue;
    }
    while(numtestdiv < numtotest) {
    if ((numtotest % numtestdiv) == 0){
    numtotest++; numtestdiv = 2; continue;
    } else {
    numtestdiv++;
    }
    }
    System.out.print(numtotest + " ");
    numtotest++; numtestdiv = 2;
    }
    }
    public static void primes12() {
    long numtotest = num1;
    long numtestdiv = 2;
    while(numtotest <= num2) {
    if(numtotest == 1) {
        numtotest++;
        continue;
    }
    while(numtestdiv < numtotest) {
    if ((numtotest % numtestdiv) == 0 || numtotest == 1) {
    numtotest++; numtestdiv = 2; continue;
    } else {
    numtestdiv++;
    }
    }
    System.out.print(numtotest + " ");
    numtotest++; numtestdiv = 2;
    }
    }
    @SuppressWarnings("empty-statement")
    public static void usereingabe () throws IOException {
        System.out.print("\n\n> ");
        BufferedReader in = new java.io.BufferedReader(new InputStreamReader(System.in));
        while((Usereingabe = in.readLine()).length() == 0);
    }
und
Code:
public static void init() {
        System.out.println("Programm zur Berechnung von Primzahlen");
        System.out.println("Fuer Hilfe geben Sie bitte ein:\n\thelp");
        System.out.println("Um Informationen zu einem bestimmten Befehl zu erhalten,");
        System.out.println("tippen Sie bitte \n\thelp [Befehl].");
        
    }
    public static void user () throws IOException {
        usereingabe();
        if(Usereingabe.charAt(0) == 'p' && Usereingabe.charAt(1) == 'r' && Usereingabe.charAt(2) == 'i' && Usereingabe.charAt(3) == 'm' && Usereingabe.charAt(4) == 'e' && Usereingabe.charAt(5) == 's') {
            if (Usereingabe.length() == 6) {
                primes();
            } else if (Usereingabe.contains("0 ") == false && Usereingabe.contains("1 ") == false && Usereingabe.contains("2 ") == false && Usereingabe.contains("3 ") == false && Usereingabe.contains("4 ") == false && Usereingabe.contains("5 ") == false && Usereingabe.contains("6 ") == false && Usereingabe.contains("7 ") == false && Usereingabe.contains("8 ") == false && Usereingabe.contains("9 ") == false) {
                int i = 7;
                while(i <= Usereingabe.length()-1) {
                    zahl1.append(Usereingabe.charAt(i));
                    i++;
                }
                    temp = zahl1.toString();    
                    num1 = Integer.parseInt(temp);
                    primes1();
        }
            else if (Usereingabe.contains("0 ")|| Usereingabe.contains("1 ")|| Usereingabe.contains("2 ")|| Usereingabe.contains("3 ")|| Usereingabe.contains("4 ")|| Usereingabe.contains("5 ")|| Usereingabe.contains("6 ")|| Usereingabe.contains("7 ")|| Usereingabe.contains("8 ")|| Usereingabe.contains("9 ")){
                int i = 7;
                while(i <= Usereingabe.length() - 1) {
                    if(Usereingabe.charAt(i) != ' '){
                        zahl1.append(Usereingabe.charAt(i));
                        i++;
                    }else{
                        i++;
                        break;
                    }
                }
                temp = zahl1.toString();
                num1 = Integer.parseInt(temp);
                while(i <= Usereingabe.length() - 1) {
                    zahl2.append(Usereingabe.charAt(i));
                    i++;
                }
                temp = zahl2.toString();
                num2 = Integer.parseInt(temp);
                primes12();
            }
        }
    }
    public static void main(String[] args) throws IOException {
        init();
        while(true) {
            user();
        }
    }

Wenns nötig ist, gebe ich auch noch den ganzen Quelltext her.

Hat irgendjemand eine Idee, wo die Bugs sitzen könnten?

Vielen Dank für jeden Beitrag,
LG runagrog
 
1.) warum legst du static variablen an. meine profs sagten mal, dass wäre ne todsünde
2.) markiere mal bitte den teil wo du die primzahl prüfst und die passende schleife
3.) schaff dir mal nen formatter an...
 
1. Wieso? Bin noch relativ neu dabei, wo liegt der Nachteil? Bei mir meckert Netbeans sonst immer rum...
2.
Code:
public static void primes1() {
long numtotest = 1;
long numtestdiv = 2;
while(numtotest <= num1) {
if(numtotest == 1) {
numtotest++;
continue;
}
while(numtestdiv < numtotest) {
if ((numtotest % numtestdiv) == 0){
numtotest++; numtestdiv = 2; continue;
} else {
numtestdiv++;
}
}
System.out.print(numtotest + " ");
numtotest++; numtestdiv = 2;
}
}
Das wäre der Teil, in welchem ich Primzahlen bis hin zu einer bestimmten, vorher durch den Benutzer festgelegten Zahl berechnen lasse. Als kurze Erklärung:
Die Variable numtotest ist immer die Zahl, über die ich wissen will, ob sie prim ist. Nach einem Durchlauf wird sie inkrementiert. Die Variable numtestdiv steht für die Zahl, durch die eben numtotest "gemodoluliert" wird, um herauszufinden, ob sie nicht prim ist. Sollte sich herausstellen, das die Zahl nicht prim ist, wird mit continue ein neuer Durchlauf veranlasst (mit vorherigem Inkrement von numtotest), und wenn eben alle Tests kein negatives Ergebnis liefern, wird die Zahl eben auf dem Bildschirm ausgegeben. Bei der 1 funktioniert das nicht, deshalb habe ich da eine Sonderbehandlung eingebaut, die sofort ausgeführt wird.

Zu 3.: KA warum da Netbeans manchmal net klarkommt... Gibts da externe Programme oder Plugins, die man da mal drüberlaufen lassen könnte?

LG runagrog
 
Die Sonderbehandlung für die 1 ist Quatsch. Einfach bei der zwei anfangen und gut ist.
Und mit formatieren bzw. Einrücken ist das hier gemeint. Dein Code ist ohne Einrückungen immer schlecht lesbar. Soetwas sollte man sich angewöhnen.

Code:
    public static void primes1() {
       long numtotest = 1; //gleich mit 2 starten
       long numtestdiv = 2;

       while(numtotest <= num1) {
          if(numtotest == 1) {
          numtotest++;
          continue;
         } //komplett unnötig

          while(numtestdiv < numtotest) {
             if ((numtotest % numtestdiv) == 0){
                numtotest++; 
                numtestdiv = 2; 
                continue; // nett gedacht, aber du testet sowieso immer bis zur nächsten Primzahl, da in dieser while-Schleife immer nur nach der gerade gesteteten Zahl geschaut wird
             } else {
                numtestdiv++;
             }
          }

          System.out.print(numtotest + " ");
          numtotest++; 
          numtestdiv = 2;
    }
}

In der zweiten Schleife brichst du immer erst ab, wenn du eine Primzahl gefunden hast. Fängst du also bei 8 an, sucht er dort die nächste Primzahl (11). Erst wenn er die gefunden hat, kommt die Abbruchbedingung der äußeren Schleife zur Geltung. Dann ist nämlich 12 > 10... Dein Problem liegt also in der Abbruchbedingung der zweiten Schleife.
 
1. Statische Variablen sind keine Todsünde, wenn man weiß, wie man sie richtig einsetzt.
Statische Variablen haben eigentlich den Zweck, dass sie objektübergreifend für das Objekt immer gleich sind. Ändert sich die statische Variable in einem Objekt, dann ändert sie sich bei allen Objekten dieser Art.

Benutze bitte bei den Namen für Variablen und Funktionen small Camelcase.
Benutze bitte returns und gib die Werte so zurück, das geht schon bei der Usereingabe los.
Behandle deine Fehler richtig. Einfach immer throwen bis ganz nach oben ist schlechter Stil und auch nicht wirklich hilfreich.
Deine If's und else's sind ekelhaft lang. Lager die Überprüfung in eine Funktion aus und gib true oder false zurück. Alternativ benutze RegEx. (Zahl + Leerzeichen ist einfach).
Warum gibt es die Funktion um nach Primzahlen zu suchen 3 mal? Bitte gründlicher Überlegen, wie man das kompakter machen könnte. Und wenn man es nicht kann, dann bitte ordentlicher benennen.

2.
Du braucht in der 2ten While innerhalb der if-else kein continue. Entweder es wird if oder else ausgeführt und da beide kein Break enthalten, landest du eh wieder oben in der Überprüfung für die While-Schleife.

In der 2ten While-Schleife liegt auch der Fehler. In der If-Frage nimmst du den Modulo und erhöhst danach numtotest um 1. Nun gibst du numtotest aus und erst danach überprüfst du, ob numtotest überhaupt in dem Bereich liegt indem du Suchen willst.
Bauen also vorher sowas ein ...

Code:
...
                     while( numtestdiv < numtotest ) {
                            if( (numtotest % numtestdiv) == 0 ) {
                                   numtotest++;
                                   numtestdiv = 2;
                            }
                            else {
                                   numtestdiv++;
                            }
                     }
                     if(numtotest > num1){
                            break;
                     }
                     
                     System.out.print(numtotest + " ");
                     numtotest++;
                     numtestdiv = 2;
              }
...
Um die Ausgabe zu Verhindern und die Schleife dann auch vorzeitig abzubrechen
 
Zuletzt bearbeitet:
Der Code ist ne mittelschwere Katastrophe, aber hier schonmal die Ursache.

Erstmal gescheite Formatierung, damit man überhaupt etwas sieht. Das würde ich Dir auch sehr empfehlen, sonst blickst bei noch komplizierteren Programmen erst recht nicht durch:

Code:
public static void primes1()
{
	long numtotest = 1;
	long numtestdiv = 2;
	
	while(numtotest <= num1)
	{
		if(numtotest == 1)
		{
			numtotest++;
			continue;
		}
		while(numtestdiv < numtotest)
		{
			if ((numtotest % numtestdiv) == 0)
			{
				numtotest++;
				numtestdiv = 2;
				continue;
			}
			else
			{
				numtestdiv++;
			}
		}
		
		System.out.print(numtotest + " ");
		numtotest++; numtestdiv = 2;
	}
}

Problem ist die innere Schleife in Zeile 13. Die Schleife wird nicht verlassen, es sei denn numtestdiv ist wirklich mal größer oder gleich numtotest.

Ansonsten static ist nicht Totsünde es gibt schon berechtigte Fälle, aber nicht wenn man damit nur Variablen an Methoden übergibt. Die Eingabevalidierung ist auch nicht der Hit, es gibt in Java bestimmt String Methoden, die Dir von links X Stellen wiedergeben, die könntest dann mit .equals("primes") oder so überprüfen. Oder den Eingabestring generell an Leerstellen splitten, Anzahl der Splitparts überpüfen und dann den jeweiligen Inhalt. Details kenne ich leider nicht, komme aus der C# Ecke... Ansonsten fehlt jegliche Dokumentation im Code, so dass es nicht gerade leicht ist sich da einzulesen als fremder.

Nur mal so als Denkanstöße für weiteren Code...

Edit: Und um den Algorithmus schon mal etwas effizienter zu gestalten: Es reicht zu testen bis numtestdiv > numtotest/2 ist...
 
Zuletzt bearbeitet:
Erst mal vielen Dank für die Hilfe! Konnte erst jetzt wieder reinschauen. Ich hab das Programm jetzt gemäß den meisten von euren Vorschlägen umgesetzt, und es funktioniert, wie es sollte. Nochmal vielen Dank :)
 
Zurück
Oben