Code in C schreiben, der auf primzahl prüft?

4 Antworten

Der ganz klassische Ansatz geht in Pseudocode so:

Zahl = Eingabe
Für test = 2 bis Wurzel(Zahl):
  Wenn Zahl modulo test gleich 0 ist:
    keine Primzahl, Schleife abbrechen
Falls Schleife nie abgebrochen wurde, ist Zahl eine Primzahl

Du testest deine Zahl nacheinander mit dem gesamten Zahlenbereich möglicher Teiler durch. Wenn eine Zahl ein Teiler ist, ist der Modulo = 0 und du weißt, dass es keine Primzahl ist. Du könntest natürlich mit dieser Methode auch alle Primfaktoren bestimmen. Etwas optimieren könne man noch, indem man den Teiler 2 separat testet und dann nur alle ungeraden durchgeht.

Eine andere Möglichkeit ist das bereits angesprochene Sieb des Erastosthenes. Das eignet sich, um Primzahlen eines ganzen Zahlenbereiches zu finden. Dabei erzeugst du ein Array von bool-Werten (bzw. in c int-Werte) in der Größe des Zahlenbereichs (von 0 beginnend) und gehst alle Vielfachen durch und setzt die Felder auf false.

Woher ich das weiß:Studium / Ausbildung – info studium
Schachpapa  20.10.2021, 22:29
Etwas optimieren könne man noch, indem man den Teiler 2 separat testet und dann nur alle ungeraden durchgeht.

Oder 2 und 3 vorab und dann ab 5 abwechselnd in 2er und 4er Schritten:

5,7, 11,13, 17,19, 23,25, 29,31, usw.

0
veeQuZ 
Fragesteller
 20.10.2021, 22:44

Kann leider dem nicht folgen, was du geschrieben hast und in welchem Zusammenhang Wurzeln jetzt darin stehen

Danke, könntest du das bitte noch etwas erläutern? 

Angenommen, ich möchte die Zahl 105 testen, also 

int main () {

int nummer 105 = 105;

printf(„Ist d% eine primzahl?\n“, nummer); 

n= 1;

n+1;

if 102 % n =/ 0 -> prim 

else 102 % n +1 

wäre das so ganz grob korrekt? Mir fällt leider das „Vokabular“, das korrekt auszudrücken 

Könntest du das bitte irgendwie ergänzen/korrigieren? ._.
danke!

0

Probiere in einer Schleife mögliche Teilerkandidaten aus. Wenn bei einer anderen Zahl als 1 und der zu prüfenden Zahl der Rest 0 herauskommt, ist es keine Primzahl und du kannst aufhören. Bei deinem Beispiel wäre das schon bei 3 der Fall.

Wenn das funktioniert, kannst du dir Gedanken machen, ob du vielleicht nicht alle Zahlen zwischen 2 und n-1 ausprobieren musst.

veeQuZ 
Fragesteller
 20.10.2021, 22:41

Danke, könntest du das bitte noch etwas erläutern?
Angenommen, ich möchte die Zahl 105 testen, also

int main () {

int nummer 105 = 105;

printf(„Ist d% eine primzahl?\n“, nummer);

n= 1;

n+1;

if 102 % n =/ 0 -> prim

else 102 % n +1

wäre das so ganz grob korrekt? Mir fällt leider das „Vokabular“, das korrekt auszudrücken

wäre das in Ordnung?

0
Schachpapa  20.10.2021, 22:48
@veeQuZ
int main () {

int nummer = 105;

printf(„Ist %d eine primzahl?\n“, nummer);

teiler = 1;
Schleifenanfang <- Hier musst du mal nachdenken
  {
  teiler = teiler+1;
  rest = nummer % teiler;
  if (rest == 0) {
    // nicht prim, abbrechen
  }
// Wenn kein teiler mit rest == 0 gefunden, 
// dann ist es eine Primzahl
// (außer wenn teiler == nummer, 
// denn das geht ja immer glatt auf)

Ich will dir nicht alles vorschreiben, dann hast du ja keinen Lerneffekt. Programmieren lernt man nicht vom Zugucken, sondern vom Selbermachen. Genau wie Radfahren.

0
veeQuZ 
Fragesteller
 20.10.2021, 22:56
@Schachpapa

Danke, das hatte ich auch nicht erwartet.

Der Schleifenanfang ist ja der Anfang, wenn die schleife nochmals durchlaufen wird, und die wird ja nur durchlaufen, wenn die Zahl prim ist, richtig?

0
Schachpapa  20.10.2021, 23:00
@veeQuZ

Ja, aber das weißt du ja vorher nicht.

Die Schleife sollte mindestens so oft durchlaufen werden, bis klar ist, ob es sich um eine Primzahl handelt oder nicht. Und das weißt du spätestens dann, wenn du mit teiler bei der zu prüfenden Zahl (nummer) angekommen bist und bis dahin keine Zahl (teiler) gefunden hast, bei der der rest 0 bleibt. Eigentlich auch schon vorher, aber es muss ja nicht gleich im ersten Anlauf optimal sein.

0
veeQuZ 
Fragesteller
 20.10.2021, 23:03
@Schachpapa

Danke, d.h., dass dann der Schleifenanfang nummer / teiler ist?

und dann eine else-Schleife folgt?

0
Schachpapa  20.10.2021, 23:18
@veeQuZ

Else-Schleife? Das habe ich noch nie gehört, wohl das Gegenstück dazu.

Du stehst noch sehr am Anfang der Programmierung, nicht wahr? Und dann C als erste Programmiersprache, du Armer!

Der Schleifenanfang wäre:

while (teiler < nummer) {

Das ganze Ding kann man auch formulieren als:

int nummer = 105; // das sollte man eingeben können
int teiler = 1;
int rest = 1; // sonst wird die Schleife nicht betreten

while (teiler < nummer && rest > 0) {
  teiler = teiler + 1;
  rest = nummer % teiler;
}

if (teiler < nummer) 
  printf("%d ist nicht prim\n",nummer);
else // dann ist teiler == nummer
  printf("%d ist prim\n",nummer);

Verstehst du das oder brauchst du Erklärungen?

Den Fall nummer==1 müsste man gesondert behandeln, denn 1 ist keine Primzahl.

0
veeQuZ 
Fragesteller
 20.10.2021, 23:24
@Schachpapa

Kann man so sagen haha, 1. Semester Studium

Das ist aber einleuchtend, nachdem man das so gehört hat.

Nur int rest = 1 verstehe ich nicht, wieso wird die schleife nicht betreten?

genauso wie das doppel und-zeichen bei nummer und und rest

Könntest Du das nochmal erklären, bitte?

0
Schachpapa  20.10.2021, 23:27
@Schachpapa

Ich gehe jetzt schlafen, daher noch kurz die Erklärung:

nummer ist 105, teiler ist 1, rest auch.

Zu Beginn der Schleife gilt: 1 < 105 und 1 > 0 also Schleifenrumpf ausführen

teiler wird 2, rest wird 105%2 also 1

Schleifenbedingung prüfen: 2 < 105 und 1 > 0 also Schleifenrumpf ausführen

teiler wird 3, rest wird 105%3 also 0

Schleifenbedingung prüfen: 3 < 105 aber 0 == 0 also fertig.

3 < 105 also keine Primzahl.

0
Schachpapa  20.10.2021, 23:31
@veeQuZ
Nur int rest = 1 verstehe ich nicht, wieso wird die schleife nicht betreten?
genauso wie das doppel und-zeichen bei nummer und und rest

rest muss mit (irgend)einem Wert >0 vorbesetzt werden, sonst ist die Schleifenbedingung von vornherein nicht erfüllt und es würde direkt nach der Schleife weiter gehen.

Dass Doppel-& bedeutet, dass sowohl teiler < nummer als auch rest > 0 gelten muss, damit der Schleifenrumpf ausgeführt wird. Wenn eine der beiden Bedingungen false ergibt, geht es nach der Schleife weiter. Wenn die erste Bedingung false ergibt, wird beim Doppel-& die zweite erst gar nicht geprüft.

So, Nacht jetzt!

0
veeQuZ 
Fragesteller
 21.10.2021, 15:28
@Schachpapa

Hi, danke, das habe ich soweit verstanden.

Mein code sind folgendermaßen aus:

#include <stdio.h>

int main() {

    {int nummer = 22201;

    int teiler = 1;

    int rest = 1;

    while (teiler < nummer && rest > 0){

        teiler = teiler +1;

        rest = nummer % teiler;

}

}

if (teiler < nummer)

    printf("%d ist nicht prim\n",nummer);

    else

    printf("%d ist prim\n",nummer);

aber da kommt folgende fehlermeldung:

 error: use of undeclared identifier 'teiler'

if (teiler < nummer)

  ^

prim.c:15:14: error: use of undeclared identifier 'nummer'

if (teiler < nummer)

       ^

prim.c:16:31: error: use of undeclared identifier 'nummer'

    printf("%d ist nicht prim\n",nummer);

                   ^

prim.c:18:25: error: use of undeclared identifier 'nummer'

    printf("%d ist prim\n",nummer);

                ^

prim.c:23:1: error: expected '}'

^

prim.c:3:12: note: to match this '{'

int main() {

      ^

5 errors generated.

0
Schachpapa  21.10.2021, 16:15
@veeQuZ
#include <stdio.h>
int main() {
    {int nummer = 22201;
    int teiler = 1;
    int rest = 1;
    while (teiler < nummer && rest > 0){
        teiler = teiler +1;
        rest = nummer % teiler;
    }
    }
    if (teiler < nummer)
      printf("%d ist nicht prim\n",nummer);
    else
      printf("%d ist prim\n",nummer);

Vor "int nummer = ..." steht eine {-Klammer, die da nicht hingehört. Ebensowenig das Gegenstück dazu über "if (teiler < ..."

Am Ende fehlt die schließende Klammer, die bei main geöffnet wird.

Durch die beiden zu löschenden Klammern hast du einen Block geschaffen, in dem die Variablen nummer, teiler und rest loka sind. Deshalb bekommst du außerhalb dieses Blocks die 4 Fehlermeldungen über "undeclared identifier". Der letzte Fehler ist die fehlende schließende Klammer am Ende.

0
Schachpapa  21.10.2021, 16:28
@Schachpapa

Und wenn das läuft, änderst du die while Bedingung zu:

while (teiler*teiler < nummer && rest > 0) {

und nach der Schleife

if (rest == 0)

Dann läuft es insbesondere bei sehr großen Zahlen schneller. Damit man richtig große Zahlen hat, müsste man wohl den Datentyp von zahl, teiler und rest auf "long int" oder "long long int" ändern.

0

evtl mit % teilung mit Rest und dann probierst du das für zahl%2 zahl%3 zahl%7 usw aus und schaust ob das Ergebnis 0 ist, sonst primzahl

Eine Zahl kann kein Rest haben - eine Division schon

Im einfachsten Ansatz versuchst du einfach deine Zahl durch alle Zahlen vorher zu teilen, wenn immer ein Rest übrig bleibt ist es ne Primzahl

Einfache Verbesserungen: Nur bis Wurzel(n) gehen, nur durch Primzahlen teilen