# Primzahlen mit Programm ermitteln



## Bertelcraft (9. Oktober 2007)

Hallo!
Ich habe mir ein kleines Programm geschrieben, mit dem ich Primzahlen berechnen will.
Leider gibt die Konsole immer vollkommen "irre" Werte aus. Kann mir wer sagen warum?

```
#include <cstdlib>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
    int Zahl = 10;
    int Ergebnis;
    int Rechner = 1; 
    
    cout << "Primzahlen" << endl;
    
    for(int Zaehler = 2;Zaehler < Zahl; Zaehler++) //Hier soll jede Zahl vor der maximal Zahl durchgegangen werden
    {
            for(int a = 0; Rechner < Zaehler; Rechner++) //Hier wird die Zahl, die in der Variable Zähler steht, durch alle Zahlen davor dividiert, 
                                                         //ob der Rest 0 ist. Wenn der Rest 0 ist, ist es keine Primzahl, sonst wäre sie ja eine.
            {
            Ergebnis = Zaehler%Rechner;
            if(Ergebnis != 0)
            {
              
                        cout << Ergebnis << endl;
            }
            else
            {}
            
            }
            Rechner = 1; //Hier wird der Rechner wieder auf 1 zurück gesetzt, dass wieder alle Zahlen vor Zaehler durchlaufen werden können.
    }
    system("PAUSE");
    return EXIT_SUCCESS;
}
```


----------



## deepthroat (9. Oktober 2007)

Hi.

Dein Algorithmus ist falsch. Um zu testen ob eine Zahl *n* eine Primzahl ist, mußt du (trivialer Weise) für alle Zahlen von 2 bis *(n -1)* testen ob eine von diesen Teiler der Zahl n ist.

Nur wenn *keine* Zahl gefunden werden konnte, dann ist die Zahl eine Primzahl.

Du läßt aber jede Zahl als Primzahl durchgehen, für die du *eine* Zahl findest, die *kein* Teiler ist von n.

Außerdem läßt du dir den Rest der Ganzzahldivision ausgeben. Vermutlich möchtest du die Primzahl ausgeben wenn du eine gefunden hast.

Schreib dir am besten erstmal eine Funktion, die dir berechnet ob eine einzelne Zahl eine Primzahl ist. Diese Funktion kannst du dann später in eine Schleife einbauen.

Gruß


----------



## derpfaff (9. Oktober 2007)

Ein Tipp noch: Es reicht aus von 2 bis *n/2* zu testen, da ein Teiler größer als n/2 nie eine ganze Zahl ergeben kann.

Gruß,
derPfaff


----------



## Bertelcraft (9. Oktober 2007)

Ich komm einfach nicht drauf. Ich hab den Code jetzt umgeschrieben, aber er geht immer noch nicht so wie ich wollte.

Das ist die main()-Funktion:

```
int main(int argc, char *argv[])
{
    int n = 10;
        bool Primzahl;
    int Ergebnis;
    for(int z = 1; z<n-1; z++)
    {
            Ergebnis = Rechner(n, Primzahl);
            if(Primzahl = true)
            { cout << n << endl;}
            else
            {}
    }
    
    system("PAUSE");
    return EXIT_SUCCESS;
}
```
und das ist die  Berechnung für die Primzahl:

```
int Rechner(int n, bool Primzahl)
{

    for(int i = 2; i==n-1; ++i)
    {
            
            if(n%i == 0)
            {
                        Primzahl = true;
                        
            }
            else
            {
                        if(Primzahl != false)
                        { Primzahl = false; }
                        else
                        {}
            }
    }
    return Primzahl;

}
```
Ich finden den Fehler nicht. Ich habe wohl einen kleinen Denkfehler.


----------



## deepthroat (9. Oktober 2007)

Hi.

Es scheint jetzt bist du völlig raus.

Du hast die Funktion zu kompliziert gemacht.

Die Funktion sollte folgende Signatur haben:
	
	
	



```
bool primzahl(int x);
```
Wenn du innerhalb der Funktion in der Schleife einen Teiler findest, kannst du sofort false zurückgeben. Wurde die Schleife in der Funktion komplett abgearbeitet - also es wurde kein Teiler gefunden - dann gibst du true zurück.

Du verwendest gar nicht den Rückgabewert der Funktion. So sollte es innerhalb der Schleife aussehen:
	
	
	



```
if (primzahl(z)) {
  cout << z << endl;
}
```
Gruß


----------



## Nogg (19. Oktober 2008)

Okay, ich recycle mal diesen älteren Thread: Hallo erstmal.

Ich habe grade vor zwei Tagen angefangen, mich mit C++ zu beschäftigen und habe als Fingerübung auch mal ein Primzahl-Programm versucht:


```
int main()
{
	int zahl, teiler, max;
	bool prim;
	cout << "Primzahlen berechnen bis zu: ";
	cin >> max;
	cout << "\n";
	for(zahl = 2; zahl <= max; zahl++)
	{
		prim = true;
		for(teiler = 2; teiler < zahl; teiler++)
		{
			if(zahl % teiler == 0)
			{
				prim = false;
			}
		}
		if(prim == true) {
			cout << zahl << " ";
		}
	}
	cout << "\n" << endl;
	system("PAUSE");
        return EXIT_SUCCESS;
}
```

Das ganze funktioniert super, die Lösung kommt mir allerdings ein wenig unelegant vor.
Deswegen mal meine Frage an die Cracks hier: Gibt es eine elegantere Lösung und wenn ja, wie sieht die aus?


----------



## RedWing (19. Oktober 2008)

Hallo,


Nogg hat gesagt.:


> Das ganze funktioniert super, die Lösung kommt mir allerdings ein wenig unelegant vor.
> Deswegen mal meine Frage an die Cracks hier: Gibt es eine elegantere Lösung und wenn ja, wie sieht die aus?



ja gibt es. Es ist ja so das wenn du eine Zahl überprüfst ob sie sich durch einen Teiler teilen lässt, den entgegengesetzten Teiler auch gleich mit prüfst. Bspw. Wenn 15 durch 3 teilbar ist, ist 15 auch durch 5 teilbar. Du erreichst den "entgegengesetzten" Teiler nach der Wurzel der Zahl. D.h. also das deine innere Schleife nur bis zur Wurzel der Zahl prüfen muss:


```
for(zahl = 2; zahl <= max; zahl++)
{
  int maxTeiler;
  maxTeiler = = ((int) sqrt(zahl));
  prim = true;
  for(teiler = 2; teiler < maxTeiler; teiler++)
  {
...
```

Um noch ein bisschen Optimierung rauszuholen kannst du auch mit dem Produkt rechnen:


```
int teiler = 2;
...
for(zahl = 2; zahl <= max; zahl++)
{
  int sqrTeiler;
  sqrTeiler = teiler * teiler;
  for(teiler = 2; sqrTeiler < zahl; teiler++)
  {
...
```

Welche von beiden Varianten jetzt schneller ist ist schwer zu sagen, jedoch schon um einiges schneller als die Variante in der der Teiler immer bis == zahl überprüft werden muss.

btw seh grad noch: Desweiteren kannst du innerhalb von


```
if(zahl % teiler == 0)
{
  prim = false;
  break;
}
```
ein break einführen, sodass er aus der inneren Schleife rausspringt sobald es keine Primzahl mehr sein kann.


Gruß,
RedWing


----------



## Nogg (20. Oktober 2008)

Hallo,



RedWing hat gesagt.:


> btw seh grad noch: Desweiteren kannst du innerhalb von
> 
> 
> ```
> ...


Stimmt, das ist mir auch grade noch aufgefallen. :-(
Danke, diese Änderung bringt natürlich eine _ganz_ erhebliche Performance-Steigerung.

Im Grunde wollte ich aber eher darauf hinaus, ob die Lösung mittes der _prim_-Variable in meinem Beispiel in Ordnung ist, oder ob es da bessere Lösungen gäbe (mal unabhängig davon, ob eine solche Lösung performanter wäre; letztlich will ich ja kein praxisorientiertes Programm, sondern das ganze sollte nur eine persönliche Übung sein.)
Ich habe es ja so gelöst, dass die rabiable initial auf 1 gesetzt wird und dann bei einem Schleifenaufruf auf 0 gesetzt wird, wenn es keinen Rest gibt.
Wenn ich 5 überprüfe, will ich ja wissen, ob bei derTeilung durch 2 _oder_ 3 _oder_ 4 kein Rest bleibt. Die Lösung mit der _prim_-Variable kommt mir (intuitiv) ein wenig umständlich vor. Gibt es eventuell eine [bessere] Möglichkeit, das z. B. in _einen_ Ausdruck zu verpacken?


```
prim = true;
		for(teiler = 2; teiler < zahl; teiler++)
		{
			if(zahl % teiler == 0)
			{
				prim = false;
```
Danke erstmal schon für die Antwort soweit.


----------



## deepthroat (20. Oktober 2008)

Hi.





Nogg hat gesagt.:


> Die Lösung mit der _prim_-Variable kommt mir (intuitiv) ein wenig umständlich vor. Gibt es eventuell eine [bessere] Möglichkeit, das z. B. in _einen_ Ausdruck zu verpacken?


Die eleganteste Lösung ist meiner Meinung nach eine eigene Funktion für den Primzahltest zu verwenden.

Gruß


----------

