www.matheraum.de
Das Matheforum.
Das Matheforum des MatheRaum.

Für Schüler, Studenten, Lehrer, Mathematik-Interessierte.
Hallo Gast!einloggen | registrieren ]
Startseite · Forum · Wissen · Kurse · Mitglieder · Team · Impressum
Forenbaum
^ Forenbaum
Status Mathe
  Status Schulmathe
    Status Primarstufe
    Status Mathe Klassen 5-7
    Status Mathe Klassen 8-10
    Status Oberstufenmathe
    Status Mathe-Wettbewerbe
    Status Sonstiges
  Status Hochschulmathe
    Status Uni-Analysis
    Status Uni-Lin. Algebra
    Status Algebra+Zahlentheo.
    Status Diskrete Mathematik
    Status Fachdidaktik
    Status Finanz+Versicherung
    Status Logik+Mengenlehre
    Status Numerik
    Status Uni-Stochastik
    Status Topologie+Geometrie
    Status Uni-Sonstiges
  Status Mathe-Vorkurse
    Status Organisatorisches
    Status Schule
    Status Universität
  Status Mathe-Software
    Status Derive
    Status DynaGeo
    Status FunkyPlot
    Status GeoGebra
    Status LaTeX
    Status Maple
    Status MathCad
    Status Mathematica
    Status Matlab
    Status Maxima
    Status MuPad
    Status Taschenrechner

Gezeigt werden alle Foren bis zur Tiefe 2

Navigation
 Startseite...
 Neuerdings beta neu
 Forum...
 vorwissen...
 vorkurse...
 Werkzeuge...
 Nachhilfevermittlung beta...
 Online-Spiele beta
 Suchen
 Verein...
 Impressum
Das Projekt
Server und Internetanbindung werden durch Spenden finanziert.
Organisiert wird das Projekt von unserem Koordinatorenteam.
Hunderte Mitglieder helfen ehrenamtlich in unseren moderierten Foren.
Anbieter der Seite ist der gemeinnützige Verein "Vorhilfe.de e.V.".
Partnerseiten
Mathe-Seiten:Weitere Fächer:

Open Source FunktionenplotterFunkyPlot: Kostenloser und quelloffener Funktionenplotter für Linux und andere Betriebssysteme
StartseiteMatheForenC/C++Dauerschleife/While
Foren für weitere Studienfächer findest Du auf www.vorhilfe.de z.B. Astronomie • Medizin • Elektrotechnik • Maschinenbau • Bauingenieurwesen • Jura • Psychologie • Geowissenschaften
Forum "C/C++" - Dauerschleife/While
Dauerschleife/While < C/C++ < Programmiersprachen < Praxis < Informatik < Vorhilfe
Ansicht: [ geschachtelt ] | ^ Forum "C/C++"  | ^^ Alle Foren  | ^ Forenbaum  | Materialien

Dauerschleife/While: Dauerschleife
Status: (Frage) beantwortet Status 
Datum: 14:10 Do 13.11.2014
Autor: Haloelite

Aufgabe
Gegeben ist eine monoton wachsende Funktion f(x) in einem Intervall [a,b] mit f(a) < 0 und f(b) > 0.
Die Nullstelle im Intervall [a,b] lässt sich durch Intervallschachtelung nach folgendem Algorithmus
bestimmen:
1. Berechne den Intervallmittelpunkt m := (a + b) / 2.
2. Falls f(m) > 0, dann betrachte [a,m] (die untere Hälfte des betrachteten Intervalls) als das
nächste zu bearbeitende Intervall, andernfalls das Intervall [m,b] (die obere Hälfte des betrachteten
Intervalls).
3. Wiederhole die Schritte 1. und 2. solange, bis |f(m)| genügend klein ist, d.h. kleiner als eine
vorgegebene Konstante Epsilon (0.01) ist.

Mein Problem liegt in der while-Schleife, die mir immer nur 4 bestimmte Werte liefert und das dauerhaft.
Ich poste zum Verständnis einfach mal den ganzen Code, vielleicht kann mir ja jemand weiter helfen.
Ich sitze nämlich fest.
Danke im Voraus.

#include <stdio.h>
#define Epsilon 0.01

float nullstelle(float k, float l)                              
{
    float p;
    p = (k+l)/2;

    return p;
}

float funktion(float x)
{
    float y;
    y = (x*x) - 5;

    return y;
}


            float main (void)
            {
                float m, a, b, Erg;
                printf("Bitte Werte fuer a und b eingeben.");
                scanf("%f %f", &a, &b);

                m = nullstelle(a,b);
                printf("Mittelwert: [mm] %f\n", [/mm] m);

                Erg = funktion(m);

                if(funktion(m)>0)
                {
                    m = nullstelle(a,m);
                }
                else
                {if(funktion(m)<0)
                    {
                    m = nullstelle(m,b);
                    }
                }

                printf("Mittelwert nach Funktionswertuebergabe = % f", m);

                if(Erg<0)
                {
                    Erg = Erg*(-1);
                }

                            while(Erg>=Epsilon)
                            {
                                Erg = funktion(m);

                                if(Erg<0)
                            {
                                Erg = Erg*(-1);
                            }


                            if(funktion(m)>0)
                            {
                                m = nullstelle(a,m);
                            }
                            else
                            {if(funktion(m)<0)
                                {
                                m = nullstelle(m,b);
                                }
                            }


                            printf("Ergebniswert: %f", Erg);
                        }
            }

        
Bezug
Dauerschleife/While: Antwort
Status: (Antwort) fertig Status 
Datum: 14:46 Do 13.11.2014
Autor: Event_Horizon

Hallo!

zunächst ist ein #define etwas, das man sehr sehr häufig verwendet. Aber es können auch unerwartete Effekte entstehen. wenn du z.B. folgendes verwendest:


printf(" Epsilon wurde unterschritten, Schleife bricht jetzt ab.")

erhälst du als Ausgabe:

"0.01  wurde unterschritten, Schleife bricht jetzt ab."

denn das #define ersetzt JEDES Vorkommen des Worts Epsilon.

besser:

const float Epsilon = 0.01;


Nun zu deinem Code:

                Erg = funktion(m);
                if(funktion(m)>0)

Warum nutzt du nicht einfach Erg? Jedes mal, wenn du funktion(m) aufrufst, wird diese Funktion erneut ausgeführt. Es macht also Sinn, den Wert  einmal in Erg zu speichern, und dann nur noch diese Variable zu verwenden.

1:
2: if(funktion(m)>0)
3:                 {
4:                     m = nullstelle(a,m);
5:                 }
6:                 else
7:                 {if(funktion(m)<0)
8:                     {
9:                     m = nullstelle(m,b);
10:                     }
11:                 } 


OK, m ist der Wert zwischen a und b. Wenn du  m = nullstelle(m,b); schreibst, was machtg dein Code dann mit dem neuen Wert von m? Nichts mehr!

Im Prinzip ist es doch so: Wenn m>0 ist, dann soll m der neue Wert von b werden, sonst der neue Wert von a. Also eher a = nullstelle(m,b)


Dann versuchst du da was mit nem Vorzeichen... Schreib doch lieber   while(Erg> -Epsilon && Erg < Epslion)

Und generell ist mir nicht klar, was du mit dem Code vor der while-Schleife machen möchtest. Im Prinzip reicht doch das, was in der while-Schleife steht.





Bezug
                
Bezug
Dauerschleife/While: Verbesserung:
Status: (Frage) beantwortet Status 
Datum: 15:33 Do 13.11.2014
Autor: Haloelite

Ich habe meinen Code jetzt verbessert, erhalte allerdings immer noch eine Dauerschleife:

#include <stdio.h>

float nullstelle(float k, float l)
{
    float p;
    p = (k+l)/2;

    return p;
}

float funktion(float x)
{
    float y;
    y = (x*x) - 5;

    return y;
}


            float main (void)
            {
                const float Epsilon = 0.01;
                float m, a, b, Erg;

                    printf("Bitte Werte fuer a und b [mm] eingeben.\n"); [/mm]
                    scanf("%f %f", &a, &b);

                    m = nullstelle(a,b);
                    Erg = funktion(m);

                            while(Erg> Epsilon || Erg < 0)
                            {
                                m = nullstelle(a,b);
                                Erg = funktion(m);

                                if(Erg>0)
                                {
                                    b = nullstelle(a,m);
                                }
                                    else
                                    {
                                        if(Erg<0)
                                        {
                                        a = nullstelle(m,b);
                                        }
                                    }
                            printf("Ergebniswert: %f", Erg);
                            }
            }

Bezug
                        
Bezug
Dauerschleife/While: Antwort
Status: (Antwort) fertig Status 
Datum: 17:29 Do 13.11.2014
Autor: Event_Horizon

Hallo!


So sieht das schon besser aus.

Wie du in deinem anderen Beitrag schreibst, hatte ich nen Fehler bei der while-Schleife. Aber du meinst nun sicher auch eher
while(Erg> Epsilon || Erg < -Epsilon)

Nun zu deinem Code:

1:
2: while(Erg> Epsilon || Erg < 0)
3: {
4:     m = nullstelle(a,b);
5:     Erg = funktion(m);
6:
7:     if(Erg>0)
8:     {
9:         b = nullstelle(a,m);
10:     }
11:     else
12:     {
13:         if(Erg<0)
14:         {
15:         a = nullstelle(m,b);
16:         }
17:     }
18: ... 


In Zeile 4 berechnest du den neuen Mittelpunkt.
Liegt der Funktionswert über 0, berechnest du nochmal einen neuen Mittelpunkt, und zwar zwischen a und dem bereits berechneten Mittelpunkt. Das heißt, das neue Intervall entspricht dem unteren Viertel des alten. Zugegeben, ich habe das eben auch nicht gesehen.

Jedenfalls ist es nun möglich, daß du mit dem oberen Wert bereits unter die Nullstelle rutschst, und so die Nullstelle gar nicht mehr im Intervall liegt. Das gibt ne Endlosschleife. Es muß heißen:

1:
2:
3:     if(Erg>0)
4:     {
5:         b = m;
6:     }



Ansonsten kannst du ggf. auch noch eine printf-Anweisung in die While-Schleife einbauen, um dir nach jedem Durchlauf a, b und m auszugeben. Daran kannst du auch ablesen, ob es funktioniert.

Bezug
                                
Bezug
Dauerschleife/While: Danke =)
Status: (Mitteilung) Reaktion unnötig Status 
Datum: 12:17 Fr 14.11.2014
Autor: Haloelite

Danke für die nette Hilfe von allen.
jetzt wird der Funktionswert auch kleiner als Epsilon. :)

Bezug
        
Bezug
Dauerschleife/While: Rückfrage
Status: (Frage) beantwortet Status 
Datum: 14:56 Do 13.11.2014
Autor: Haloelite

Hallo,
Ich verstehe nicht, was du mit
while(Erg> -Epsilon && Erg < Epslion) meinst.
Die Schleife soll doch wiederholt werden, wenn Erg eben nicht den Wert >Epsilon hat, damit es kleiner wird.
Mit while(Erg> -Epsilon && Erg < Epslion) geht man doch davon aus, dass der
Wert schon zwischen -Epsilon und Epsilon liegt?


Bezug
                
Bezug
Dauerschleife/While: Antwort
Status: (Antwort) fertig Status 
Datum: 17:14 Do 13.11.2014
Autor: Event_Horizon

hallo!

Da hast du natürlich recht!

Bezug
                        
Bezug
Dauerschleife/While: Rückfrage2
Status: (Frage) beantwortet Status 
Datum: 18:20 Do 13.11.2014
Autor: Haloelite

Aber dennoch funktioniert mein Programm nicht und spuckt mir falsche Ergebnisse aus. :/
Weiß jemand, warum? ich habe über legt, komme aber nicht drauf.

Bezug
                                
Bezug
Dauerschleife/While: Mitteilung
Status: (Mitteilung) Reaktion unnötig Status 
Datum: 20:43 Do 13.11.2014
Autor: chrisno

Ich kenne mich mit der Sprache nicht so gut aus. Macht es kein Problem, dass in der Funktion kein Dezimalpunkt hinter der 5 ist?

Bezug
                                
Bezug
Dauerschleife/While: Antwort
Status: (Antwort) fertig Status 
Datum: 21:08 Do 13.11.2014
Autor: chrisno

Ich denke, Du solltest den von Event_Horizon vorgezeichneten Weg weiter gehen.
Dass Du bei der Eingabe nicht abprüfst, ob f(a) < 0 und f(b) > 0 wird Dir hier erstmal keine Probleme machen. Früher oder später wird sich so etwas sicher rächen.

Vor der Schleife
m = Nullstelle(a;b)
Erg = f(m)
Nun aber zur Schleife:
Solange abs(Erg) > Eps
Wenn Erg) > 0, dann a = m
sonst b = m
(Das setzt voraus, dass f auf dem Intervall monoton steigt. Damit schließt Du die Hälfte der Nullstellen von vornherein aus. Das lässt sich aber in einer späteren Version noch in Ordnung bringen.)
Nun m = Nullstelle(a;b)
dann Erg = f(m)
Schleifenende

Bezug
                                        
Bezug
Dauerschleife/While: Hmm?
Status: (Frage) beantwortet Status 
Datum: 12:23 Fr 14.11.2014
Autor: Haloelite

Hallo,
danke für den Hinweis.
Das mit dem abs(Erg) habe ich auch schon probiert, da hat er nicht reagiert.

Aber wieso ist deine Bedingung in der While-Schleife denn
"while(abs(Erg) > Eps)"?
Natürlich, das mit <Epsilon ergibt Sinn.
Aber so werden doch Werte < 0 vernachlässigt, weshalb die Schleife abbrechen würde?


Bezug
                                                
Bezug
Dauerschleife/While: Antwort
Status: (Antwort) fertig Status 
Datum: 13:37 Fr 14.11.2014
Autor: Event_Horizon

Hi!


abs()  oder fabs() sind Funktionen, die dir den Betrag einer Zahl liefern. Dummerweise funktionieren sie in C nur für ganze Zahlen (integer).

Stattdessen kannst du fabs() verwenden, musst dann aber #include <math.h> einfügen.

Bezug
                                                        
Bezug
Dauerschleife/While: Okay
Status: (Mitteilung) Reaktion unnötig Status 
Datum: 10:41 Mo 17.11.2014
Autor: Haloelite

Gut, danke. =)

Bezug
Ansicht: [ geschachtelt ] | ^ Forum "C/C++"  | ^^ Alle Foren  | ^ Forenbaum  | Materialien


^ Seitenanfang ^
www.matheforum.net
[ Startseite | Forum | Wissen | Kurse | Mitglieder | Team | Impressum ]