Verhindern, dass Programm "abgestürzt" aussieht



  • kommt drauf an was du machst, wenn du weißt wie viele Schleifendurchgänge du machst oder wie viele Rekursionen du durchführst könntest du es machen,
    was machst du denn ? Das ist IMMER Situatuionsabhängig



  • Wie gesagt, ich habe ein Programm zur Primzahlfaktorzerlegung geschrieben.

    Hier siehst du den Code, falls es dich interessiert:

    double w;
    bool b = false;
    int xx,yy;
    TStringList *Primzahlen;
    Primzahlen = new TStringList;
    xx =1;
    yy =1;
    int c = StrToInt (Edit1->Text);//Diese Zahl wird untersucht
    for (int i=2; i<=c; i++) //Hier werden alle Primzahlen ermittelt, die kleiner als die eingegebene Zahl
    			//sind, und in der StringList "Primzahlen" abgespeichert
    {
    	for (int x=2; x<i; x++)
    	{
    	w = fmod(i,x);
    		if (w == 0)
    		{
                    break;
    		}
             Application->ProcessMessages();
    
    	}
                     if (w!=0)
                    {
                    /*StringGrid1->RowCount = yy+1;
                    StringGrid1->Cells[xx][yy] = IntToStr (i);
                    yy++;*/
                    Primzahlen->Add (IntToStr(i));
                    }
             Application->ProcessMessages();
    
    }
            for (int i=Primzahlen->Count-1; i>=0; i--) //Hier wird ermittelt ob die zu untersuchende Zahl
            {                                          //schon eine Primzahl ist; wenn dies der Fall ist
            if (c == Primzahlen->Strings[i])	   //wird die Zahl in der Tabelle angezeigt und der weitere Vorgang nicht durchgeführt (b = true)
            {
            StringGrid1->RowCount = yy+1;
            StringGrid1->Cells[xx][yy] = IntToStr(c);
            b = true;
            break;
            }
             Application->ProcessMessages();
            }
    while ( b == false) //wiederholt sich sooft, bis alle Faktoren gefunden sind
    {
    
    	for (int i=Primzahlen->Count-1; i>=0; i--)
    	{
    		if (/*double u = */fmod(c,StrToInt(Primzahlen->Strings[i])) ==0) //es wird geschaut, ob eine Primzahl ein Teiler von der zu ermittelnden Zahl ist
    		{StringGrid1->RowCount = yy+1;
            	StringGrid1->Cells[xx][yy] = Primzahlen->Strings[i];
            	c =c/StrToInt(Primzahlen->Strings[i]); //wenn dies der Fall ist, wird mit dem übrigen Faktor weitergerechnet
                    yy++;
                    break;
    		}
             Application->ProcessMessages();
    
    	}
            for (int i=Primzahlen->Count-1; i>=0; i--)     //ob dieser übriggebliebene Faktor schon eine Primzahl ist, wird in dieser for Schleife untersucht
            {
             ;
            if (c == Primzahlen->Strings[i])
            {
            StringGrid1->RowCount = yy+1;
            StringGrid1->Cells[xx][yy] = IntToStr(c);
            b = true;                                      //ist dies der Fall hört die while Schleife auf (b= true)
            break;
            }
             Application->ProcessMessages();
            }
             Application->ProcessMessages();
    }
    Primzahlen->SaveToFile ("Primzahlen.txt");
    

    Also, ich sehe nicht, wie ich hier die Anzahl der Schleifendurchgänge, schon im voraus ermitteln kann. Übrigens: Was meinst du genau mit Rekursionen? (bin c++ Anfänger)
    Trotzdem, es wäre toll, wenn mir jemand sagen könnte, ob ich jetzt hier den Fortschritt der Rechenoperationen mit einer ProgressBar anzeigen lassen kann oder nicht. (und wie das funktioniert)

    Vielen Dank



  • Ich seh was ich machen kann, was ist fmod ?
    Ich wollte dir das einbauen, aber ich sende den Code gleich ohne testen.
    Ich würde nähmlich den Code testen, mit der ProgressBar,
    und ohne zu wissen was fmod ist wird das schwer.
    und ja es sieht so aus als wäre es möglich.
    (Ich kenn das nur um Musik zu spielen o.0)

    EDIT: Leider ist mir nur eine recht primitive Art eingefallen, aber anders geht es nicht, weil sich die Anzahl der Schleifendurchgänge nicht vorhersehen lässt.

    double w;
    bool b = false;
    int xx,yy;
    TStringList *Primzahlen;
    Primzahlen = new TStringList;
    xx =1;
    yy =1;
    
    ProgressBar1->Maximum = 4;
    ProgressBar1->Position++;
    int c = StrToInt (Edit1->Text);//Diese Zahl wird untersucht
    for (int i=2; i<=c; i++) //Hier werden alle Primzahlen ermittelt, die kleiner als die eingegebene Zahl
    			//sind, und in der StringList "Primzahlen" abgespeichert
    {
    	for (int x=2; x<i; x++)
    	{
    	w = fmod(i,x);
    		if (w == 0)
    		{
    				break;
    		}
    		 Application->ProcessMessages();
    
    	}
    				 if (w!=0)
                    {
                    /*StringGrid1->RowCount = yy+1;
                    StringGrid1->Cells[xx][yy] = IntToStr (i);
                    yy++;*/
                    Primzahlen->Add (IntToStr(i));
                    }
             Application->ProcessMessages();
    
    }
    ProgressBar1->Position++;
            for (int i=Primzahlen->Count-1; i>=0; i--) //Hier wird ermittelt ob die zu untersuchende Zahl
            {                                          //schon eine Primzahl ist; wenn dies der Fall ist
            if (c == Primzahlen->Strings[i])       //wird die Zahl in der Tabelle angezeigt und der weitere Vorgang nicht durchgeführt (b = true)
    		{
    		StringGrid1->RowCount = yy+1;
    		StringGrid1->Cells[xx][yy] = IntToStr(c);
    		b = true;
    		break;
    		}
    		 Application->ProcessMessages();
    		}
    		ProgressBar1->Position++;
    while ( b == false) //wiederholt sich sooft, bis alle Faktoren gefunden sind
    {
    
    	for (int i=Primzahlen->Count-1; i>=0; i--)
        {
            if (/*double u = */fmod(c,StrToInt(Primzahlen->Strings[i])) ==0) //es wird geschaut, ob eine Primzahl ein Teiler von der zu ermittelnden Zahl ist
    		{StringGrid1->RowCount = yy+1;
    			StringGrid1->Cells[xx][yy] = Primzahlen->Strings[i];
    			c =c/StrToInt(Primzahlen->Strings[i]); //wenn dies der Fall ist, wird mit dem übrigen Faktor weitergerechnet
                    yy++;
                    break;
            }
             Application->ProcessMessages();
    
        }
            for (int i=Primzahlen->Count-1; i>=0; i--)     //ob dieser übriggebliebene Faktor schon eine Primzahl ist, wird in dieser for Schleife untersucht
            {
             ;
            if (c == Primzahlen->Strings[i])
            {
            StringGrid1->RowCount = yy+1;
    		StringGrid1->Cells[xx][yy] = IntToStr(c);
            b = true;                                      //ist dies der Fall hört die while Schleife auf (b= true)
            break;
            }
             Application->ProcessMessages();
            }
             Application->ProcessMessages();
    }
    ProgressBar1->Position++;
    Primzahlen->SaveToFile ("Primzahlen.txt");
    

    Rekursion ist hier nicht vorhanden, es war ja auch nur eine möglichkeit.
    Was das ist wäre jetzt zu kompliziert um es kurz zu fassen.

    EDIT2: btw: der Code sieht grausam aus 😉



  • fmod berechnet den Modulus einer Divison, also den Rest.
    Sieht dann so aus: bei der Divison von x/y ist der Rest fmod (x,y);
    Dafür musst du math.h "includen".

    Danke für deine Hilfsbereichtschaft. Werde es in Kürze ausprobieren. Hätte eigentlich selber draufkommen müssen.

    Übrigens: Was heißt hier "der Code sieht grausam" aus? 😉

    Gruß,
    sceche



  • Die Einrückung ist ähm nun ja sehr eigenwillig,
    manchmal gar nicht eingerückt.
    Sehr schlecht lesbar.



  • Die häufigen Aufrufe von ProcessMessages reduzieren aber auch die Performance. Als Faustregel gilt, etwa alle 10ms einen Aufruf zu machen.

    Jedoch würde ich auch gerade für diese Aufgabe einen eigenen Thread präferieren...



  • Wie ich ja geschrieben habe, bin ich kein Profi-Programmierer. Ich habe noch nie mit Threads gearbeitet und keine Ahnung wie ich mit Ihnen umgehe. Wär nett, wenn mir jemand sagen könnte, wie das ungefähr mit C++-Builder funktioniert.

    Danke 🙂



  • Hallo

    Für Threads gibts im Forum extra ein Tutorial.

    bis bald
    akari



  • Man kann auch noch den Algorithmus optimieren:

    1. alle Primzahlen ausser 2 sind ungerade, daher kannst du die äussere Schleife so formulieren (musst natürlich die 2 als Sonderfall statisch aufnehmen):
    for( int x = 3; x < c; x += 2 )
    
    1. Der grösste ganzzahlige Teiler von P ist die Wurzel aus P, ausserdem ist der Teiler niemals gerade (siehe Punkt 1). Damit sähe die innere Schleife dann so aus:
    int MaxIter = sqrt( x );
    for( int i = 3; i <= MaxIter; i += 2 )
    

    Damit wirfst du schon einmal einen Grossteil unnötiger Berechnungen über Bord und dein Programm wird wesentlich schneller. Von der Benutzung von ProcessMessages rate ich dringend ab, klick doch einfach mal auf das CloseWindow Icon des Formulars, während die Primzahlberechnung läuft.



  • Danke für eure Hilfe! 🙂



  • DocShoe schrieb:

    1. alle Primzahlen ausser 2 sind ungerade, daher kannst du die äussere Schleife so formulieren (musst natürlich die 2 als Sonderfall statisch aufnehmen):

    Tatsächlich musst Du nicht einmal alle ungeraden Zahlen prüfen, sondern nur die Primzahlen bis zur Wurzel der zur prüfenden Zahl. Das sind dann noch einmal deutlich weniger Operationen... Aber schnell wird es erst mit einem Prime-Sieve.


Anmelden zum Antworten