Laden...

[gelöst] Consolenanwendung: PrimzahlenRechner ergibt falsche Primzahlen!

Erstellt von Kamas vor 14 Jahren Letzter Beitrag vor 14 Jahren 3.593 Views
K
Kamas Themenstarter:in
3 Beiträge seit 2009
vor 14 Jahren
[gelöst] Consolenanwendung: PrimzahlenRechner ergibt falsche Primzahlen!

Hallo!
Bin gerade durch meine Ausbildung neu in C# eingestiegen!

Wir hatten die Aufgabe einen vorgegebenen Pseudo-Code-Algorithmus mit Hilfe von C# zum lauffähigen Programm zu programmieren.

Nun habe ich den gesamten Code bereits in C# übersetzt und das Programm läuft auch.
Leider liegt ein Rechenfehler vor. Das Programm gibt falsche Primzahlen heraus.
Z.B. die 15, denn bei der Abfrage der Zahl 15 kann er nur auf true kommen da:
denn für die Ausgabe von p überprüft er vorher ob tt >p ist.
Das Programm bringt in der Do-Schleife solange t=t+2 bis er bei dem wert von t=5 ist damit er false bei der OR abfrage rausbekommt. dann geht er weiter und er harpert genau bei der Ausgabe für p t
t>p sein. also lässt er 15 einfach zu.
Ich komme gerade nicht auf eine logische Lösung.bin schon ein paar Varianten durchgegangen.Daher bitte ich um neue Ideen, da mein Kopf grade platzt 😄

hier der Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace conprimzahlen
{
    class Program
    {
        static void Main(string[] args)
        {
            
                Console.WriteLine("Geben Sie eine obere Grenze ein");
                //int n = Convert.ToInt32(Console.ReadLine());
                int n = int.Parse(Console.ReadLine());

                if (n >= 2) //2 ist die kleinste Primzahl
                {
                Console.WriteLine("2");
                int p;
                int t;
                p = 3;  
                    while (p <= n)
                    {

                        t = 1;
                        do
                        {


                            t = t + 2;
                            
                        }

                        while ((p % t == 1) | (t*t < p));
                        
                        if (t * t > p)
                            {
                                Console.WriteLine(p);
                            }
                        
                        p = p + 2;

                    }

                   


                }
        }
    }
}

Glück bleibt Glück, Wissen ist Macht!

J
3.331 Beiträge seit 2006
vor 14 Jahren

Hallo und willkommen,

bitte überarbeite zunächst deinen Beitrag, damit er lesbar ist. Siehe Wie poste ich richtig? Punkt 6. Das kannst du auch nachträglich ändern: Beitrag zum Editieren öffnen, Code-Bereich markieren, auf den #-Button drücken, speichern.

So will ich deine Beschreibung nicht mit dem Code überprüfen.

Gruß Jürgen

PS. Ein paar Kleinigkeiten konnte ich trotzdem erkennen:

  1. Besser so:
while ((p % t == 1) || (t*t < p))

Das Semikolon am Ende dieser Zeile ist mit Sicherheit falsch!

  1. Ist wirklich modulo 1 gemeint?

  2. Verkürzte Addition:

t += 2;  // statt t = t + 2
S
21 Beiträge seit 2009
vor 14 Jahren

Hallo und willkommen,

  1. Besser so:
while ((p % t == 1) || (t*t < p))  

Das Semikolon am Ende dieser Zeile ist mit Sicherheit falsch!

es steht aber


do
{


t = t + 2;

}

while ((p % t == 1) | (t*t < p));

also ist es richtig

K
Kamas Themenstarter:in
3 Beiträge seit 2009
vor 14 Jahren

bitte überarbeite zunächst deinen Beitrag, damit er lesbar ist.

  1. Ist wirklich modulo 1 gemeint?

  2. Verkürzte Addition:

t += 2;  // statt t = t + 2  

Erstmal Danke an euch!
Hallo Juetho

zu dem Punkt Überarbeitung.
Das verstehe ich gerade nicht. Ich hab doch Thema Entwicklung gewählt und meine Überschrift ist auch aussagend.Was genau willst du mir damit sagen?
Vllt das der Code richtig angezeigt wird oder im Anhang als Bild?

zum 2 Punkt. laut dem pseudocode ist modulo 0 denn es steht (p % t ==0 ) so im Pseudocode. Doch ich musste das ganze sozusagen negieren, weil er sonst für
while ((p % t == 1) | (t*t < p)); immer den wert TRUE ausgegeben hätte und die Schleife sich dadurch unendlich wiederholt hätte.

zum 3 Punkt. Danke das mit dem + = +1 kannte ich 😄, habe ich an dieser Stelle nurnochnicht umgesetzt bzw. ist mir als Neuling noch nicht so wichtig gewesen oder aufgefallen =). Habe ich aber jetzt umgesetzt.

Und ja am ende der do-while schleife steht ein Semikolon, wie SEKKIY sagt ist es richtig, sonst würde das Programm garnicht laufen oder eine Ausgabe auflisten.

TROTZDEM suche ich noch eine mögliche Antwort zu meiner Frage.
Ich überlege vllt die Abfrage zu ändern. da primzahlen ja NUR durch sich und durch 1 teilbar sind aber nicht durch z.b. 11/3 = 3,66periode. das heißt ja ich kann gut mit modulo arbeiten. wenn REST also 1 da ist ist es eine primzahl.

EDIT! ok ich brauche für meine do-while schleife einen abbruch falls ein Wert true ist.
d.h. while ((p % t == 0) | (t*t > p)); da muss ein wert true sein damit er weitermacht im programm. Im Moment sieht es so aus, dass wenn einer der Werte true ergibt er die Schleife immer wiederholt.Das sehe ich im Debugmodus.Er kommt also nicht aus der Schleifen ich brauch den Abbruchbefehl. Bzw. er macht nur im Programm weiter wenn beide Werte False sind. also muss ich das irgendwie NEGIEREN aber wie. wenn ich beides negiere wird ein wert trotzdem ja true sein...

Glück bleibt Glück, Wissen ist Macht!

S
64 Beiträge seit 2008
vor 14 Jahren

Hallo,

ändere mal die do-while-Schleife in


while ((p%t != 0) && (t*t < p))

Denn die Schleife soll ja solange wiederholt werden, wie kein Rest entsteht und der Teiler kleiner als die Wurzel der aktuellen Zahl ist.

Des weiteren die auch die nachfolgende if-Abfrage entsprechend anpassen


if((t * t > p) && (p % t != 0))

Denn die Zahl ist ja nur dann prim, wenn ein Rest != 0 aufgetreten ist und der Teiler größer ist als die Wurzel der Zahl.
Und hier liegt auch dein Problem mit der 15. Die do-while-Schleife hat nämlich bei t = 5 abgebrochen und da 5*5 = 25 > 15 ist war die if-Bedingung erfüllt und er hat das ganze als Primzahl ausgegeben.

Allerdings musst du nach den Änderungen noch einen Sonderfall, neben der 2, behandeln, nämlich die 3, aber da kommst du bestimmt von selbst drauf, wo uns wie 😁

Grüße

J
3.331 Beiträge seit 2006
vor 14 Jahren

also ist es (das Semikolon) richtig

OK, den Zusammenhang mit dem do habe ich nicht gesehen; siehe den nächsten Punkt:

zu dem Punkt Überarbeitung.
Das verstehe ich gerade nicht. Ich hab doch Thema Entwicklung gewählt und meine Überschrift ist auch aussagend.Was genau willst du mir damit sagen?
Vllt das der Code richtig angezeigt wird ...

Ich will, dass der Code-Auszug in einem Kasten steht und als C#-Code gekennzeichnet ist (wie bei den anderen Beiträgen). Dann sind nämlich auch Schlüsselwörter und Einrückungen lesbar.

Eine Arbeitsanleitung dazu habe ich gegeben, und es steht auch in "Wie poste ich richtig?". Bitte erledige das. 🙄

Jürgen

K
Kamas Themenstarter:in
3 Beiträge seit 2009
vor 14 Jahren

YEAH! ICH HABS 😄 ganz alleine sogar.
Danke trotzdem für die hilfe mit der Schleife ändern usw.

Und zwar habe ich ( auch gepostet die juetho es wollte )

          do
                        {
                            t += 2; //t=t+2 laut Pseudo-Code ist eine lange Variante
                            if ((p % t == 0) | (t * t > p))
                                break;
                            else
                                continue;
                        } while (true);

Glück bleibt Glück, Wissen ist Macht!

5.299 Beiträge seit 2008
vor 14 Jahren

hier ist if oder else-Zweig redundant, verbessert also:


                        do
                        {
                            t += 2; 
                            if ((p % t == 0) | (t * t > p))break;
                        } while (true);

naja, dann kann die Bedingung (in Negation) auch gleich in den while-Ausdruck:


                        do
                        {
                            t += 2; 
                        } while ((p % t != 0) && (t * t <= p));

Das Kurzschluß-AND "&&" ist dem einfachen AND "&" fast immer vorzuziehen, weil es die Auswertung des 2. Teilausdrucks überspringt, wenn der erste Teil-Ausdruck schon false ergibt.
(analog Kurzschluß- Or "||" dem einfachen vorziehen)

Als Merk-Hilfe vlt. die VB.Net-Bezeichner: Dort heisstes AndAlso respektive OrElse, womit das Verhalten des Operators klar bezeichnet ist.

Der frühe Apfel fängt den Wurm.