Anzahl Primzahlen zwischen 1 und 10 = 27 ??



  • Hallo zusammen,
    ich bin ein C++ Neuling und arbeite mich derzeit durch das Buch "Einstieg in C++" von Arnold Willemer.
    Ich hab ein Programm erstellt, das mir berechnet welche Primzahlen es zb. zwischen 1-100 gibt. (Listing in dem Buch: Primzahlen.cpp / S.107)
    Jetzt wollte ich es so verändern, dass es mir auch zusammenrechnet wieviele Primzahlen in dem Zahlenbereich vorhanden sind.
    Das ist der Code:

    #include <iostream>
    using namespace std;
    
    int main()
    {
    int MaxPrimzahl;
    int Primzahl, Divisor;
    bool istEinePrimzahl;
    int AnzahlPrimzahlen;
        cout << "Bitte geben Sie eine Zahl ein!" << endl;
        cin >> MaxPrimzahl;
        cout << "Primzahlen: 1, 2";
        AnzahlPrimzahlen + 2;
        for (Primzahl=3; Primzahl<=MaxPrimzahl; Primzahl++)
        {
            istEinePrimzahl = true;
            // Pruefe, ob Primzahl wirklich eine Primzahl ist
            for (Divisor=2; Divisor<Primzahl; Divisor++)
            {
                // Ist das restlos teilbar?
                if (0==Primzahl % Divisor)
                {
                    // Zahl ist teilbar, also keine Primzahl!
                    istEinePrimzahl = false;
                }
    
            }
            // Pruefung ist beendet.
            // Wenn es eine Primzahl ist, ausgeben!
            if (istEinePrimzahl)
            {
                AnzahlPrimzahlen++;
                cout << ", " << Primzahl ;
            }
    
        }
        cout << " " << endl;
        cout << "Anzahl: " << AnzahlPrimzahlen << endl;
    }
    

    Auf den ersten Blick scheint es zu funktionieren. Aber die Angabe der Anzahl der Primzahlen ist nicht immer richtig ^^. wenn man 10 eingibt kommt zb dann 27 raus...

    hat jmd ne idee wo mein fehler liegt ?

    mfg Insahne



  • Erstens mußt du die Variable am Anfang noch initialisieren und zweitens macht der Ausdruck 'AnzahlPrimzahlen + 2;' keinen Sinn.

    Am besten du arbeitest dich gleich mit einem Debugger ein (je nachdem, welche IDE du benutzt), dann kannst du Schritt für Schritt die Variablenwerte überprüfen und siehst den Fehler sofort...

    P.S. es gibt bessere (schnellere) Primzahl-Algorithmen (such mal hier im Forum danach).
    Zumindestens solltest du ein 'break' nach dem 'istEinePrimzahl = false;' setzen, damit die Schleife nicht weiter durchlaufen wird...

    Und noch etwas: 1 ist keine Primzahl...



  • AnzahlPrimzahl + 2, weil die Primzahlen 1 und 2 in der Rechnung nicht vorkommen (erst ab 3 wird ausprobiert, siehe Zeile 14,

    Primzahl=3

    )

    und initialisieren ? ich denk die variablen werden durch "int" initialisiert? oder nicht ? ansonsten steht (bis jetzt) in dem Buch nix von initialisieren.

    danke für den Tipp mit dem debugger, werd mich mal umschaun

    *edit: oh ^^ stimmt 1 ist keine Primzahl. lustigerweise wurde im Buch selbst auch nur 2 eingefügt, im Listing auf der CD dann aber auch 1 ^^.



  • ok, wenn du meintest das ich AnzahlPrimzahlen am anfangen = 0 setzen muss, dann habs ich verstanden, jetzt funktioniert es auch 🙂

    Er hatte wohl AnzahlPrimzahlen immer auf 24 gesetzt weil ich keinen bestimmten Wert angegeben hatte.

    Danke für deine schnelle Antwort TH ^^



  • #include <iostream>
    #include <iomanip>
    #include <vector>
    #include <sstream>
    
    void calc_prim(unsigned long, std::vector<unsigned long>&);
    inline std::streamsize num_len(std::size_t);
    
    template <typename T> T wtype(std::wistream& in, std::wstring const &prompt) 
    {
    	T tmp;
    	do
    	{
    		std::wcout << prompt << std::endl;
    		in.sync(); in.clear(); in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    	} while (!(in >> tmp));
    	return tmp;
    }
    
    int main()
    {
    	std::vector<unsigned long> prims;
    	calc_prim(wtype<unsigned long>(std::wcin, L"Bitte geben Sie einen Wertebereich ein (0 bis ...): "), prims);
    	std::wcout << L"Primzahlen (" << prims.size() << L"): " << std::endl;
    	std::streamsize count_num_width = num_len(prims.size());
    	for (std::size_t i = 0; i < prims.size(); ++i)
    		std::wcout << std::setw(count_num_width) << std::setfill(L'0') << i << L": " << prims.at(i) << std::endl;
    }
    
    void calc_prim(unsigned long max, std::vector<unsigned long>& dest)
    {
    	dest.clear(); dest.push_back(2);
    	for (unsigned long prim = 3; prim <= max; prim += 2)
    	{
    		bool is_prim = true;
    		for (std::size_t div = 2; div < prim; div += 2) 
    			if ((prim % div) == 0) is_prim = false;
    
    		if (is_prim == true) dest.push_back(prim);
    	}
    }
    
    inline std::streamsize num_len(std::size_t num)
    {
    	std::ostringstream ss;
    	ss << num;
    	return static_cast<std::streamsize>(ss.str().length());
    }
    

    ... dann hast du einmal alles als Funktion ausgelagert ... und kannst ziiiemlich große Zahlen berechnen ...



  • Wenn du noch keinen Debugger hast, dann gib mal nach der Variablendeklaration den Wert aus (am besten mehrfach testen):

    int AnzahlPrimzahlen;
    cout << AnzahlPrimzahlen << endl;
    

    Lokale Variablen sind uninitialisiert, d.h. du mußt der Variablen explizit einen Wert zuweisen, z.B.

    int AnzahlPrimzahlen = 1;
    

    Wenn du einen Wert erhöhen willst, mußt du ebenfalls eine Zuweisung durchführen:

    x = x + 1;
    

    Und dafür gibt es in C/C++ die abgekürzte Schreibweise:

    x += 1;
    

    Und für die Erhöhung um 1 sogar noch eine kürzere.
    Aber das wird dir sicherlich im Buch noch beigebracht...
    Viel Spaß noch beim C++ lernen!



  • Hallo (D)Evil, heute wohl nicht ganz dein Tag, wie?
    Schon wieder Fehler in deinem Source-Code:
    Hier die syntaktisch und auch performantere Version:

    void calc_prim(unsigned long max, std::vector<unsigned long>& dest)
    {
        dest.clear(); /*dest.push_back(1);*/ dest.push_back(2); // 1 ist keine Primzahl!!!
        for (unsigned long prim = 3; prim <= max; prim += 2) // nur ungerade auf Primzahl testen
        {
            // Variablennamen (prim) doppelt!
            bool is_prim = true;
            // nur ungerade testen
            // (eigentlich müßte hier auch noch als Abbruchbedingung sqrt(prim) hin)
            for(unsigned long div = 3; div < prim; div += 2) // gleichen Datentypen verwenden
              if((prim % div) == 0) { is_prim = false; break; } // Schleife beenden
    
            if(is_prim) dest.push_back(prim);
        } // Klammer fehlte
    }
    

    Aber ich glaube, ein Anfänger wird diesen Code noch nicht verstehen -)



  • Jaja is ja gut 😛 Es kam mir nur aufs Prinzip an ... und das Prinzip der Funktion ist einfach von Insahne übernommen, d.h. wenn +2 performanter ist, mag das sein ... nur findet man das nicht im Code von Insahne 😛



  • :> Danke dass ihr euch die zeit nehmt einem neuling das so ausfürhlich zu erklären ^^ is mir ne große hilfe

    allerdings habt ihr in euren vorschlägen jetzt schon viele Befehle die ich noch nicht kenne ^^ ich werd mich erstmal an mein buch/tutorial halten. das war jetzt ja eigentlich auch nur eine kleine übung für die verschachtelung von schleifen


Anmelden zum Antworten