www.vorhilfe.de
Vorhilfe

Kostenlose Kommunikationsplattform für gegenseitige Hilfestellungen.
Hallo Gast!einloggen | registrieren ]
Startseite · Forum · Wissen · Kurse · Mitglieder · Team · Impressum
Forenbaum
^ Forenbaum
Status Vorhilfe
  Status Geisteswiss.
    Status Erdkunde
    Status Geschichte
    Status Jura
    Status Musik/Kunst
    Status Pädagogik
    Status Philosophie
    Status Politik/Wirtschaft
    Status Psychologie
    Status Religion
    Status Sozialwissenschaften
  Status Informatik
    Status Schule
    Status Hochschule
    Status Info-Training
    Status Wettbewerbe
    Status Praxis
    Status Internes IR
  Status Ingenieurwiss.
    Status Bauingenieurwesen
    Status Elektrotechnik
    Status Maschinenbau
    Status Materialwissenschaft
    Status Regelungstechnik
    Status Signaltheorie
    Status Sonstiges
    Status Technik
  Status Mathe
    Status Schulmathe
    Status Hochschulmathe
    Status Mathe-Vorkurse
    Status Mathe-Software
  Status Naturwiss.
    Status Astronomie
    Status Biologie
    Status Chemie
    Status Geowissenschaften
    Status Medizin
    Status Physik
    Status Sport
  Status Sonstiges / Diverses
  Status Sprachen
    Status Deutsch
    Status Englisch
    Status Französisch
    Status Griechisch
    Status Latein
    Status Russisch
    Status Spanisch
    Status Vorkurse
    Status Sonstiges (Sprachen)
  Status Neuerdings
  Status Internes VH
    Status Café VH
    Status Verbesserungen
    Status Benutzerbetreuung
    Status Plenum
    Status Datenbank-Forum
    Status Test-Forum
    Status Fragwürdige Inhalte
    Status VH e.V.

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
Dt. Schulen im Ausland: Mathe-Seiten:

Open Source FunktionenplotterFunkyPlot: Kostenloser und quelloffener Funktionenplotter für Linux und andere Betriebssysteme
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.vorhilfe.de