# Hilfe bei C++ Programm



## nediptz (29. Dezember 2011)

Moin Moin,
hätte mal eine kleine Frage zu meiner Belegarbeit in Info:  


Was ist ein Konvergenzbereich?
Woran erkenne ich wie groß epsilon werden muss?

 Aufgabe: http://www.tu-chemnitz.de/informatik/friz/Grundl-Inf/Beleg/index.php


----------



## AMD (29. Dezember 2011)

1. Du bist vllt. schon selber drauf gekommen aber ich finde, dass der Konvergenzbereich auf Wikipedia gut erklärt ist:
Konvergenzbereich

2. Das mit epsilon versteh ich gerade nicht so wirklich :/

3. Ja.
Bei der Funktion "fakultaet" gibst du den Wert als Double zurück, ich denke Nachkommerstellen kann man sich da aber sparen. Zwar kein Fehler in dem Sinne aber überflüssig.

Die Fakultät würde ich an sich glaube so berechnen und nicht ständig die Funktion neu aufrufen:

```
int erg=1;

for (int i;i==1;i--)
    erg *= i;
```
Code ist zwar nicht getestet aber sollte funktionieren.

Außerdem fällt mir auf, dass du die pow Funktion benutzt, welche ja x^y berechnet, ich denke das ist aber auch ein Teil der cmath und das dürftest du ja dann nicht verwenden, oder?! ^^

fabs() könntest du außerdem auch leicht realisieren und dann sparst du dir die cmath komplett.

```
float own_fabs(float x)
{
    if (x < 0)
        x *= -1;

    return x;
}
```

Hoffe das hilft etwas


----------



## nediptz (31. Dezember 2011)

Dank erstmal für die Hilfe.

Der Konvergenzbereich ist also eine Art Definitionsbereich, so wie ich das aus der Wikipedia herauslese, oder (0<|x|<Pi, wäre dann also richtig)?

Die Geschichte mit dem Epsilon und dem "pow" werd ich kommende Woche nochmal nachfragen, ich bin ja nicht der einzige der das machen muss.


----------



## DarthDeeger (31. Dezember 2011)

Also ich habe deinen Code mal in Codeblocks gehauen und bekomme für jegliches x das ich eingebe nur das Ergebnis laut Standardfunktion, der Teil mit "Ergenis laut Bernoulli-Summenformel..." wird gar nicht angezeigt.
http://www.abload.de/image.php?img=unbenanntj73y3.jpg
Weiterhin initialisiert du zwar die Variablen "epsilon" und "B" aber weißt ihnen nirgends einen Wert zu, vllt. verstehe ich das zumindest bei "B" nicht, da ich mathematisch nicht ganz so extrem bewandert bin. Daher macht deine if-Abfrage auf 
	
	



```
epsilon > 100000
```
 bzw. da du epsilon sonst nirgends im Code verwendest (inkrementierst oder sonst was) das 
	
	



```
else epsilon < 100000
```
 keinen Sinn für mich.
"pow" gehört ansonsten genauso wie "fabs" zur cmath, das kannst du dann aber auch so wie fabs selber realisieren (nur jetzt theoretisch, Code ist nicht getestet):

```
float own_pow(float x,float y)
{
float z;
z = x^y;
return z;
}
```
Ich hoffe ich habe jetzt nicht totalen Mist verzapft und konnte helfen


MfG


----------



## Mashed (1. Januar 2012)

DarthDeeger schrieb:


> "pow" gehört ansonsten genauso wie "fabs" zur cmath, das kannst du dann aber auch so wie fabs selber realisieren (nur jetzt theoretisch, Code ist nicht getestet):
> 
> ```
> float own_pow(float x,float y)
> ...


 
Leider hast du Mist verzapft...

x^y bedeutet eine bitweise xor-Verknüpfung von x und y, nicht "x hoch y".

Wenn du eine entsprechende Funktion selbst schreiben musst, wird dir für den allgemeinen Fall nicht viel übrig bleiben als die folgende Regel zu verwenden:
pox(x,y) = exp(y * ln(x))

exp() ist dabei die natürliche Exponentialfunktion (auch e-Funktion) und ln() der natürliche Logarithmus. Beide kannst du mit Reihenentwicklungen näherungsweise berechnen.
(Allerdings kommt der Term x^k (hier ist Potenzieren gemeint, nicht xor) vor, aber k ist eine natürliche Zahl, kann also mit einer einfachen Hilfsunktion leicht berechnet werden, genauso wie Fakultät)


----------



## Dragonix (1. Januar 2012)

Falls du die pow Funktion wirklich selber schreiben musst (was ich eigentlich nicht glaub), reicht auch ne ganz triviale rekursive/iterative Lösung ohne böse Formeln; denn deine Exponenten sind immer ganzzahlig. Aber das hast du ja schon geschrieben klärst du ab.

Konvergenzbereich wurde ja schon erklärt (grob und eigentlich auch falsch gesagt: "Nur in dem Bereich funktioniert die Formel").

Das Epsilon verwendest du, um "zu schauen ob sich das Ergebnis überhaupt noch so großartig ändert, dass sich weitere Berechnungen noch rentieren": Das ist eben nicht der Fall, wenn zwei aufeinanderfolgende Werte einen Unterschied kleiner als Epsilon aufweisen. Ich denke aber, ihr bekommt das Epsilon vorgegeben; letztenendens ist's ja sowas ÄHNLICHES wie die Genauigkeit.

Ansonsten mal ein paar Kommentare:


```
if (epsilon < 100000)  ///Ist Quatsch, dein epsilon wird einen sehr kleinen wert haben. Außerdem musst du schauen, ob zwei aufeinanderfolgende Glieder sich um einen Betrag kleiner als Epsilon unterscheiden! Siehe [URL="http://www.tu-chemnitz.de/informatik/friz/Grundl-Inf/Beleg/texte/beleg111_html_m1f2fb0f9.gif"]hier[/URL]
     {
         for (n=0; n>12; n++) //Die Schleife ist falsch. n wird auf 0 initialisiert, und die Schleife wird solange ausgeführt wie n GRÖßER als 12 ist!
         cout << "Das Ergebnis mittels Summenformel lautet x = " << (pow(-1,n+1)*pow(2,2*n)/fakultaet(2*n))*B*pow(x,2*n-1);  //Summenformel heißt, dass du etwas aufaddierst. Hier addierst du aber nichts. Du musst immer die einzelnen Glieder aufsummieren, wie hier [url=http://www.tu-chemnitz.de/informatik/friz/Grundl-Inf/Beleg/texte/beleg111_html_13d0bd20.gif]hier[/url] beschrieben. Dazu brauchst du i.d.R. eine Variable. Hier musst du auch irgendwie das mit dem Epsilon managen!
     }
     else
     {
         epsilon > 100000;
         cout << "Der Abbruchwert wurde überschritten";
     }
```

Hast du die Formel mal auf dem Papier selber ausgeführt? Denk dabei werden eventuelle Unklarheiten schnell beseitigt!

Gruß
Matthias

Hoff ich hab nich zu viel Mist verbockt, ist aber noch so früh am morgen


----------



## Skysnake (1. Januar 2012)

Warum macht ihr euch son Stress?

Soweit ich das gesehen/verstanden habe, kann er auch einfach ne for-Schleife machen. Quick&Dirty nenn ich das, aber es geht ohne Probleme.


----------



## nediptz (7. Januar 2012)

Danke erstmal für die vielen Antworten, ich hab noch bissl dran rum gebaut:

1. hab eigene Pow geschrieben (verbesserungwürdig )
2. habe ein Feld angelegt in dem die Bernoulli-Zahl und das zugehörige n steht
3. Epsilon ist noch immer irgendwie unklar ... könnte sein das es durch den Nutzer des Programmes eingegeben werden soll 

Das Programm liefert noch ein paar irritierende Ergebnisse


----------



## Skysnake (7. Januar 2012)

Ich hab mal bischen was geändert


```
#include <iostream>
#include <cmath>

using namespace std;

double potenz(double basis, int exponent) // Funktion für Potenz ([COLOR=red]keine Exponenten <0 möglich){
[COLOR=red]if(exponent==0){
  double v = 1;
}
else{
  if(exponent>0){
       double v = basis;
       for (int j = 1; j < exponent; j++){
      v *= basis;
       }
  }
}return v;
}

double fakultaet (int i) // Funktion für Fakultät
{
    float erg;
    if (i <= 0)
    return 1;
    erg = i * fakultaet(i-1);
    return erg;
}

int main()

{
double x, y;
int n;
const double Pi=3.14159265;
double epsilon;
double cosh (double x);
double sinh (double x);

double B[12][2] =
{
//{n, Bernoulli}
{1, 1.0/6.0},
{2, 1.0/30.0},
{3, 1.0/42.0},
{4, 1.0/30.0},
{5, 5.0/66.0},
{6, 691.0/2730.0},
{7, 7.0/6.0},
{8, 3617.0/510.0},
{9, 43867.0/798.0},
{10, 174611.0/330.0},
{11, 854513.0/ 138.0},
{12, 236364091.0/2730.0}
};

cout << "Berechnung des coth(x) mit Bernoulli Summenformel und Standartfunktionen aus cmath" "\n";
cout << "Geben Sie x ein:";
cout << "\nx = ";
cin >> x;

if (fabs(x) < 0,fabs(x) > Pi)
    {
        cout << "Bitte x erneut eingeben (Konvergenzbereich 0<|x|<Pi)";
    }
    if (epsilon < 0.000001)
    {
        for (n=1; n<=12; n++)

        y = (potenz(-1,n+1) * potenz(2,2*n) / fakultaet(2*n)) * (**(B)) * potenz(x,2*n-1);

        cout << "Das Ergebnis mittels Summenformel lautet y = " << y << "\n";
    }
    else
    {
        epsilon > 0.000001;
        cout << "Der Abbruchwert wurde überschritten";
    }

if (fabs(x) < 0,fabs(x) > Pi)
    {
        "Bitte x erneut eingeben (Konvergenzbereich 0<|x|<Pi)";
    }
    else
    {
    cout << "Das Ergebnis mittels Standartfunktionen lautet y = " << cosh(x)/sinh(x);
    }
    return 0;
}
```


Und man sieht, du hast die SAche mit Epsilon nicht verstanden...

Hast du keine Analysis gehört? Wenn nein, schau dir bitte Konvergenzbedingungen von Folgen und Reihen an. Was du da machst ist ja nichts anderes als eine Reihenentwicklung des coth an der Stelle x...

Bitte bitte bitte nimm dir nen Analysis Buch und schau dir das an. Wenn du es nicht kapierst, kannst du auch gern Fragen, aber du weißt überhaupt nicht, ein Epsilon ist. 

PS: Epsilon-Umgebung oder Epsilon-Delta-Umgebung sind zwei gute Stichworte, für das was du hier machen sollst, wobei Epsilon-Delta schon wieder weitergehend ist. Für dich lang eigentlich die Betrachtung einer Epsilon-Umgebung.


----------



## nediptz (8. Januar 2012)

Ich glaub ich werde das Programm erstmal ohne das Epsilon erstellen,  weil ich erstmal vernünftige Funktionswerte brauche und die kriege ich  mit den 12 Summengliedern. 
@Skysnake: 
Nein ich hatte noch keine Analysis Vorlesung, die kommt erst im zweiten  Semester. Dein Vorschlag zur Verbesserung der Pow Funktion, will bei mir  nicht so richtig funktionieren. Er sagt mir ständig als Ergebnis für  x^0 ist NaN (Not a Number).Mir ist grad noch aufgefallen, die Exponenten, der jeweiligen Summenglieder sind sowieso immer positiv, deshalb brauch ich das eigentlich nicht.

Das Hauptproblem wird wohl in der Eingabe der Summenformel liegen. Ich hab mir bereits mal die Mühe gemacht und die einzelnen Glieder eingegeben, so kriege ich vernünftige Werte, aber das ist nicht Sinn der Sache, zumal ich dann Probleme beim Zahlenraum bekomme.


----------



## Skysnake (8. Januar 2012)

Ähm NotANumber sollte nicht kommen. Du fängst das ja mit der if Bedingung ab, und setzt den Rückgabewert in diesem Fall einfach auf 1. x^0 ist ja immer 1, also nur vom Exponenten abhängig. Da sollte es normal keine Probleme geben. 

Na dann ist mir so einiges klar......

Wie können die euch so ne Aufgabe geben, ohne das ihr Analysis hatte  

Da ist es ja auch kein Wunder, das du nicht vestehst was du da machst.

Also, dann kurz ein paar Erklärungen.

Das Epsilon nicht was, wo du schaust, ob das Ergebnis > oder kleiner ist.

Du machst ja eine Reihenentwicklung einer trigonometrischen Funktion. Ich hoffe das weißt du. Wenn nicht, schau dir bitte die Erklärung von wikipedia zur Reihenentwicklung der sin-Funktion an.

Da du eine Reihenentwicklung einer Funktion machst, müsstest du eigentlich erst mal prüfen, ob diese Reihenentwicklung überhaupt gegen den gesuchten Wert konvergiert. Das haben Sie euch erspart, weil es allgemein bekannt ist, dass diese Reihendarstellung konvergiert (Wenn du nicht weißt was das beudetet, frag wiki, da ist das gut erklärt). 

Da du weißt, dass die Reihenentwicklung konvergiert, kannst du Sie nun dazu nutzen, um den Wert auszurechnen.

Das machst du mit der Reihenentwicklung. Da die Reihe aber eine unendliche Reihe ist, und erst mit unendlich vielen Summanten dem Ergebnis entspricht, hast du NIE den richtigen Wert, sondern immer einen, der halt leicht abweicht. Du befindest dich in einer Epsilon-Umgebung um den richtigen Wert. 

Du brauchst also eine Abbruchbedingung, sonst würdest du ewig! rechnen ohne ein Ergebnis zu bekommen!!! Das ist wichtig, das dir das klar ist!

Du hast sogar 2 Abbruchbedingungen. 

Eine Harte: Die 12 Iterationen

und eine Weiche: die 0,00001 oder was der genaue Wert auch war.

Das ist jetzt nicht 100% sauber, aber so wird das Epsilon wohl bei euch aufgefasst werden (sonst mach es keinen Sinn), aber du musst nun bei jeder neuen Iteration, die Differenz von Schritt n und n-1 bilden, und schauen, ob das Ergebnis kleiner ist als Epsilon. Wenn es kleiner ist, dann kannst du wie bei der harten Abbruchbedingung einfach aufhören weiter zu rechnen und das Ergebnis ausgeben. Wenn das Ergebnis größer ist als Epsilon, dann rechne eine weitere Iteration und schau nochmals nach.

Ich hoffe das ist jetzt klar. 

Und bitte bitte bitte schau in ein Analysis Buch, oder zumindest mal bei wikipedia dir die Sachen bischen genauer an.

PS: Was studierst du eigentlich und wo?


----------



## nediptz (9. Januar 2012)

So bis auf den Abbruchwert Epsilon funktioniert das Programm und gibt vernünftige Funktionswerte aus.
@Skysnake Ich studiere Elektrotechnik. Mit dem Programmieren hab ichs halt einfach nich so .


----------



## AMD (9. Januar 2012)

@nediptz: Darf ich mal so am Rande fragen in welchem Semester du bist und wo du studierst? ^^


----------



## nediptz (11. Januar 2012)

So das Programm funktioniert jetzt, die Lösung stell ich aber erst Online, wenn es bewertet wurde.


----------



## Skysnake (15. Januar 2012)

Und wie siehts aus?


----------



## nediptz (24. Januar 2012)

```
//Entwicklungssystem: Code::Blocks v10.05 rev 6283; GNU GCC Compiler
//Testwerte für    x = 0.1, 1, 1.123, 2, 2.234, 3,-3, 3.1, -7, 76
//                 Epsilon = 0.0001, 0.00001, 0.000001
//spezielle Bedingnungen:   1. Bitte die x-Werte immer innerhalb des Konvergenbereichs eingeben, sonst erfolgt eine erneute Abfrage.
//                          2. Bitte Epsilonwerte immer nahe Null eingeben (Beispiele siehe Testwerte)
//                          3. Wenn x und Epsilon richtig eingegeben wurden wird das Programm ausgeführt und beendet.
//Kurzbeschreibung:
// Während des erstellens des Programmes habe ich zuerst die einzelnen Funktionen für die Potenz- und Fakultätsberechnung erstellt.
// Anschließend soll der x-Wert zur Berechnung von y=coth(x) eingegeben werden und der Abbruchwert Epsilon soll vom Nutzer festgelegt werden.
// Danach wird überprüft, ob der gegebene Konvergenzbereich eingehalten wird.
// Nun folgt die Berechnung mittels Summenformel und es wird überprüft, ob durch Eingabe des Epsilon ein Abbruch
// vor Berechnung der 12 Summenglieder möglich ist.
// Abschließend wird der coth(x) mit den Standartfunktionen aus cmath berechnet, sowie die Differenz der beiden Berechnungsmethoden ausgegeben.
//Diskussion der Ergebnisse:
// Der Unterschied zwischen den beiden Ergebnissen entsteht dadurch, das die Summenformel
// nach Bernoulli nur mit einer begrenzten Anzahl an Summengliedern berechnet wird und somit keine höhere Genauigkeit erreicht werden kann.
// Durch Hinzufügen von mehr als 12 Summengliedern wird das Ergebnis entsprechend genauer.
// Die Berechnung des coth(x)) mittels Standartfunktionen aus cmath ist im Vergleich genauer, je nachdem
// wie man den Wert runden lässt.


#include <iostream>
#include <cmath>

using namespace std;

double potenz (double basis, int exponent) // Funktion für Potenz (keine Exponenten <=0 möglich)
{
    double v = basis;
    for (int j = 1; j < exponent; j++)
    {
        v *= basis;
    }
    return v;
}

double fakultaet (int i) // Funktion für Fakultät
{
    float erg;
    if (i <= 0)
    return 1;
    erg = i * fakultaet(i-1);
    return erg;
}

int main()

{
double x, y, ycmath, yvorher;
int n;
const double Pi=3.14159265;
double epsilon;
double cosh (double x);
double sinh (double x);

// Feld mit Bernoulli-Zahlen

double B[12] = {1.0/6.0,
                1.0/30.0,
                1.0/42.0,
                1.0/30.0,
                5.0/66.0,
                691.0/2730.0,
                7.0/6.0,
                3617.0/510.0,
                43867.0/798.0,
                174611.0/330.0,
                854513.0/ 138.0,
                236364091.0/2730.0};

Anfang:

cout << "Berechnung des y = coth(x) mit Summenformel und Standartfunktionen aus cmath" "\n";
cout << "Geben Sie x ein:";
cout << "\nx = ";
cin >> x;

cout << "\n";

cout << "Geben sie den Abbruchwert Epsilon ein (Werte gegen Null waehlen, z.B. 0.00001)";
cout << "\nEpsilon = ";
cin >> epsilon;

cout << "\n";

if (fabs(x) < 0, fabs(x) > Pi)

    {
        cout << "Bitte x erneut eingeben (Konvergenzbereich 0<|x|<Pi)" << "\n";
        goto Anfang;
    }

    else

    {
        y=1/x;
        for (n=1; n<=12; n++)
        {

            y = y + (((potenz(-1,n+1) * potenz(2,2*n)) / (fakultaet(2*n))) * (B[n-1]) * potenz(x,2*n-1));

        }
            yvorher = 1/x + y;
            if (epsilon > fabs(y)-fabs(yvorher-1))

            {
                cout << "Der Abbruchswert Epsilon wurde erreicht." << "\n";
                cout << "Das Ergebnis mittels Summenformel lautet y = " << y << "\n" << "\n";
            }

            else

            {
                cout << "Das Ergebnis mittels Summenformel lautet y = " << y << "\n" << "\n";
            }
    }

    // Berechnung mittels Standartfunktionen aus cmath

    ycmath=cosh(x)/sinh(x);

    cout << "Das Ergebnis mittels Standartfunktionen lautet y = " << ycmath << "\n" << "\n";

    // Differenz, die durch die beiden Berechnungsmethoden auftritt

    cout << "Die Differenz zwischen den beiden Ergebnissen lautet:" << "\n";
    cout << "Differenz = " << ycmath-y;
    cout << "\n";
    return 0;
}
```


----------

