C++ Maschinengenauigkeit und Summen

Neue Frage »

Auf diesen Beitrag antworten »
Marcell99 C++ Maschinengenauigkeit und Summen

Meine Frage:
1)Die Maschinengenauigkeit € {epsilon} lässt sich als die kleinste positive Gleitkommazahl € {epsilon} ermitteln, so dass rd(1 + ?) > 1. Verwenden Sie dieses Verfahren um je ein C/C++ Programm zu schreiben, dass die Maschinengenauigkeit epsilon des float-, double- bzw. long double-Gleitkommasystems ermittelt.



2)Schreiben Sie ein C/C++ Programm welches für gegebenes n ? N den Wert der
Summe
s[n] = [n]Sigma[/k=1] 1/k^2

ausgibt. Überlegen Sie sich wie groß n gewählt werden muss damit alle Summanden für k > n kleiner als 10^(-6) sind.




Meine Ideen:
ich hab grad angefangen mit dem programmieren deswegen bin ich total überfordert mit der Aufgabe.

Kann jemand die Aufgaben mit mir schritt für schritt zusammen machen oder Ansätze geben. ich blick da grad echt nicht durch :/
 
Auf diesen Beitrag antworten »
eulerscheZahl

Aufgabe1:
Definiere ein Epsilon > 0 (z.B. 0.01). Solange (1+Epsilon > 1) kannst du das Epsilon verringern (halbieren). Damit kriegst du schon einen ganz brauchbaren Wert.
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
#include <stdio.h>

int main() {
	double epsilon = 0.01;
	double epsilonValid;
	while (1 + epsilon > 1)
	{
		epsilonValid = epsilon;
		epsilon /= 2;
	}
	printf("%g\n", epsilonValid);
}


Aufgabe 2:
[latex]s(n) = \sum_{k=1}^n\frac{1}{k^2}[/latex].
Was brauchst du beim Programmieren, um die Summenformel umzusetzen, wo ja mehrfach addiert wird?
Auf diesen Beitrag antworten »
Marcell99

int main(int argc, const char * argv[]) {

float a=4.0;
while (true) {
if (1.0+a>1.0) {
break;
}
a *=4;
}

cout<<"ergebnis"<<a<<endl;

double eps =0.5;
while (true) {
if (1.0 + eps> 1.0) {
break;
}
eps *=0.5;
}


cout<<"ergebnis "<<eps<<endl;

long double b=7.844;
while (true) {
if (1.0+b>1.0) {
break;
}
}
cout<<"ergebnis "<<b<<endl;

also ist dann meine Lösung falsch ;/



Aufgabe 2 )

so muss ich das eingeben
wenn das dir weiterhilft

#include <iostream>
using namespace std;
int main()
{
double sum; // Summe
int i,n;
cout <<"n eingeben"<<endl;
cin >> n;
sum=0.;
for (i=1;i<=n;i=i+1)
{
sum=sum+i-1./3.;
}
cout <<"Summe ist "<<sum<<endl;
}
Auf diesen Beitrag antworten »
eulerscheZahl

Die erste passt so nicht:
Zitat:
code:
1:
2:
3:
4:
5:
6:
7:
8:
float a=4.0;
while (true) {
if (1.0+a>1.0) {
break;
}
a *=4;
}
cout<<"ergebnis"<<a<<endl;

hier brichst du die Schleife nach dem ersten Durchlauf ab, ohne a geändert zu haben. Und wenn dein a klein genug wäre, würdest du in einer Endlosschleife landen.

Aufgabe 2 sieht schon besser aus, du musst nur die Berechnungsformel in der Schleife korrigieren. Und verwende bitte [code]...[/code], um deinen Code einzubetten.
 
Auf diesen Beitrag antworten »
Marcell99

aber warum passt das nur bei dem ersten nicht, bei den anderen geht das auch, wo ist denn der Unterschieden, wegen float????

2) #include <iostream>
using namespace std;
int main()
{
double sum; // Summe
int k,n;
cout <<"n eingeben"<<endl;
cin >> n;
sum=0.;
for (k=1;k>n;k++)
{
sum=sum+k+1./k*k.;
}
cout <<"Summe ist "<<sum<<endl;
}

so besser???
Auf diesen Beitrag antworten »
eulerscheZahl

Zur 1: die anderen sind genauso verkehrt, ich dachte es reicht, das am float zu erklären.

Zur 2:
sum=sum+k+1./k*k;
Das rote k steht so nicht in der Formel, das muss raus.
Mit der Formel berechnest du übrigens [latex]\frac{1}{6}\pi^2[/latex]
Auf diesen Beitrag antworten »
Marcell99

daaaaanke smile )))

jaa dann mach ich das mal mit deiner Lösung aber was ist denn bei dir epsilonValid;
warum steht das denn da, kann man das nicht weglassen???


denn wenn ich bei der letzten Zeile

printf("%g\n", epsValid);

schreibe wird es als Fehler angesehen erst wenn ich das in epsilon ändere, kann ich das Programm laufen lassen ://
Auf diesen Beitrag antworten »
eulerscheZahl

Wenn ich epsilon halbiere, bin ich ja irgendwann zu klein. Das merke ich aber erst, wenn es schon zu spät ist. Daher speichere ich zusätzlich den letzten Wert, für den es noch geklappt hat. Aber dank des Aufbaus von float/double könnte ich danach auch einfach wieder *2 rechnen, statt eine zweite Variable zu verwenden.

Edit (zu deinem edit):
bei mir heißt die Variable ja auch epsilonValid und nicht epsValid.
Auf diesen Beitrag antworten »
Marcell99

#include <stdio.h>

int main(int argc, const char * argv[]) {

float Zahla=1.0f;
float Zahlb;
while ((1+Zahla) >1) {
Zahla=Zahlb;
Zahlb /=2;
}

printf("%f\n",Zahla);

double epsilon = 0.01;
double epsilonValid;
while ((1 + epsilon) > 1)
{
epsilonValid = epsilon;
epsilon /= 2;
}
printf("%g\n", epsilon);



long double c=0.0234l;
long double d;
while ((1+c)>1) {
d=c;
c/=2;
}

printf("%l\n",c);

return 0;
}



kann ich das so lassen ??? sag bitte ja :/
Auf diesen Beitrag antworten »
eulerscheZahl

Schau dir beim float nochmal an, wo du welche Variable verwenden musst.
Auf diesen Beitrag antworten »
Marcell99

was meinst du jetzt damit ??
Auf diesen Beitrag antworten »
eulerscheZahl

Du teilst Zahlb durch 2, obwohl diese anfangs die temporäre Variable ist. Gleiches gilt für die Zuweisung, bei der du die Reihenfolge vertauscht hast.
Auf diesen Beitrag antworten »
Marcell99

ok hab es geändert
soo meinst du das oder ??

float Zahla=1.0F;
float Zahlb;
while ((1+Zahla) >1) {
Zahlb=Zahla;
Zahlta =1.0;

printf("%f\n",Zahla);


bei long double das selbe ??
Auf diesen Beitrag antworten »
eulerscheZahl

Bei long double passt alles.
Jetzt fehlt dir ein '}', die Variable heißt Zahlta statt Zahla und du setzt sie auf 1, statt sie zu halbieren.
Auf diesen Beitrag antworten »
Marcell99

ich hab die ja bei Zahl a auf 1 gesetzt
Auf diesen Beitrag antworten »
Marcell99

oder was bedeutet bei dir die zahl auf eins setzen ??
Auf diesen Beitrag antworten »
eulerscheZahl

Das meine ich mit Zahl auf 1 setzen:
code:
1:
Zahlta =1.0;

Hast du den Code mal laufen lassen (vermutlich nicht, sonst hättest du die fehlende Klammer bemerkt). Tu das mal und schaue, was rauskommt.
Auf diesen Beitrag antworten »
Marcell99

doch hab ich
da ist auch kein Fehler
aber wenn ich das laufen lasse steht nichts im Terminal
Auf diesen Beitrag antworten »
eulerscheZahl

Weil das Programm in einer Endlosschleife hängenbleibt.
Zahla = 1;
1+Zahla = 2, was größer ist als 1. Also setzt du in der Schleife Zahla = 1 (was es ja vorher schon war) und durchläufst die Schleife erneut. Da wird höchstens der Prozessor warm.
Auf diesen Beitrag antworten »
Marcell99

#include <stdio.h>

int main(int argc, const char * argv[]) {

float Zahla=1.0F;
float Zahlb;
while ((1+Zahla) ==1) {
Zahlb=Zahla;
Zahla=1.0;
}

printf("%f\n",Zahla);

double epsilon = 0.01;
double epsilonValid;
while ((1 + epsilon) > 1)
{
epsilonValid = epsilon;
epsilon /= 2;
}
printf("%g\n", epsilon);



long double c=0.0234L;
long double d;
while ((1+c)>1) {
d=c;
c/=2;
}

printf("%Lf\n",c);

return 0;
}
Auf diesen Beitrag antworten »
Marcell99

wo schreib ich das denn hin ?? ich bin verwirrt
deswegen ich mein pc so warm
Auf diesen Beitrag antworten »
Marcell99

warum denn gleich?? die Formel ist >1

jetzt kommt

1.000000
7.10543e-17
0.000000
Program ended with exit code: 0

raus
Auf diesen Beitrag antworten »
eulerscheZahl

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
#include <stdio.h>

int main(int argc, const char * argv[]) {
	float Zahla=1.0F;
	float Zahlb;
	while (1+Zahla > 1) {
		Zahlb=Zahla;
		Zahla /= 2; // Zahla=1.0; 
	}
	printf("float: %g\n",Zahlb);

	double epsilon = 0.01;
	double epsilonValid;
	while ((1 + epsilon) > 1)
	{
		epsilonValid = epsilon;
		epsilon /= 2;
	}
	printf("double: %g\n", epsilonValid);

	long double c=0.0234L;
	long double d;
	while ((1+c)>1) {
		d=c;
		c/=2;
	}
	printf("long double: %.30Lf\n",d);
	return 0;
}
Auf diesen Beitrag antworten »
Marcell99

bei float
printf
an dieser stelle kann ich nach dem Komma keine Zahlb eintippen nur Zahla da
zahlb nicht definiert ist

da gilt auch für die anderen
Auf diesen Beitrag antworten »
Marcell99

hab den Fehler gefunden du hast die geschweifte klammer falsch gesetzt
Auf diesen Beitrag antworten »
eulerscheZahl

Also, der Code, den ich oben kopiert habe, klappt bei mir wunderbar:
code:
1:
g++ -Wall infoboard.cpp

gibt keine Warnungen aus, ausführen kann ich auch.
Welchen Compiler verwendest du und was ist die genaue Fehlermeldung?
Auf diesen Beitrag antworten »
Marcell99

Xcode aber ich hab das jetzt
ich hab jetzt eine lange liste von float und double und long double
Auf diesen Beitrag antworten »
eulerscheZahl

Xcode ist eine Entwicklungsumgebung, das sagt nichts über den Compiler aus.
Aber wenn alles geht, soll es mir recht sein.
Auf diesen Beitrag antworten »
Marcell99

das weiß ich nicht ://

aber hast du vllt lust mir noch zu helfen ???

ich hab nämlich noch zwei Aufgaben :/

aber nur wenn du willst
Auf diesen Beitrag antworten »
eulerscheZahl

Du kannst sie ja mal einstellen - aber nur mit eigenem Lösungsansatz smile
Auf diesen Beitrag antworten »
Marcell99

Schreiben Sie ein C/C++ Programm welches den Wert der Reihe
unendlichschleife sigma k=0 x^k/k!
ausgibt, wobei alle Summanden die kleiner sind als eine vorgegebene Genauigkeit €(epsilon) vernachlässigt werden sollen. Vergleichen Sie diesen Wert für x Elemente {1, 2, 3} und für die Genauigkeit € = 10^(-6) in C/C++ zur Verfügung, sobald Sie den header math.h eingebunden haben.


ich versteh nie wie man diesen summand programmieren kann das ist total verwirrend woher weiß man wie man unendlichschleife einfügt ://
Auf diesen Beitrag antworten »
eulerscheZahl

Geht es um die Formel?
[latex]f(x) = \sum\limits_{k=0}^{\infty}\frac{x^k}{k!}[/latex]?

Wenn die Reihe konvergiert (das tut sie, entspricht e^x), werden die Summanden immer kleiner. Die letzten kann man also vernachlässigen, sodass es ausreicht, die ersten 100 oder so auszurechnen.
Auf diesen Beitrag antworten »
Marcell99

ja die Formel richtig


was meinst du mit den letzten die letzten fragen ??
Auf diesen Beitrag antworten »
eulerscheZahl

Beispiel:
[latex]x = \sum_{k=0}^{\infty}\frac{1}{10^k} = 1 + \frac{1}{10} + \frac{1}{100} + \frac{1}{1000} + \frac{1}{10000} \underbrace{+ \frac{1}{100000} + \frac{1}{1000000} + \dots}_{\hbox{unwichtig, da sehr kleine Zahlen}}[/latex]
x = 1.111111111... kann mit 1.1111 angenähert werden-
Auf diesen Beitrag antworten »
Marcell99

ahso okay das meinst du


tipp man das so ein


double sum;
int k,n;
cout <<"n eingeben"<<endl;
cin >> n;
sum=0;
for (k=0;100>n;k=k+10)
{
sum=sum+n*10*k/k;!
}


cout <<"Summe ist "<<sum<<endl;






return 0;
}
Auf diesen Beitrag antworten »
eulerscheZahl

Würde es komilieren, hättest du wieder eine Endlosschleife.
Die Summenformel ist falsch abgetippt, C kennt ! nicht also Fakultät und der Schleifenkopf kannst auch nicht (warum erhöhst du k um 10, warum prüfst du den Wert von n, nicht von k).
Auf diesen Beitrag antworten »
Marcell99

wie man die summenformel eintippt find ich voll schwer ://

ich verstehe das garnicht, das ist total verwirrend
was heißt denn komilieren ??

wie tipp man denn sonst die Fakultät ein und die Endlosschleife ??
Auf diesen Beitrag antworten »
eulerscheZahl

Kompilieren heißt, du hast gültigen Code geschrieben, den du in Maschinensprache übersetzen kannst.

Ich würde für Zähler und Nenner noch Variablen anlegen, in denen die den Wert in jedem Schleifendurchlauf ändern kannst.

code:
1:
2:
3:
4:
5:
6:
7:
double zaehler = 1, nenner = 1;
double sum = 1; //für k=0, was nicht in der Schleife berechnet wird.
for (int k = 1; k < 100; k++) {
    zaehler *= x; //x vom Nutzer eingelesen
    nenner *= k;
    sum += zaehler/nenner;
}
Auf diesen Beitrag antworten »
Marcell99

das verstehe ich nicht

warum schreibst double sum =1 ?? und was hat das mit k=0 zu tun ? den Zusammenhang verstehe ich nicht.

und warum soll es nicht berechnet werden in der Formel steht doch das es bei K= 0 anfängt ??

steht das hier * für die Fakultät ??
und was bedeutet das += ??


und du hast ja schrieben x wird vom Nutzer eingelesen soll ich da ein cout machen ??
Auf diesen Beitrag antworten »
eulerscheZahl

sum ist deshalb 1, weil ich k eben nicht bei 0 anfangen lasse. Und der Summand für k=0 ist eben 1.

Die Fakultät musst du im Gesamtzusammenhang sehen: das wird bei jedem Schleifendurchlauf berechnet.
nenner *= k; heißt soviel wie nenner = nenner * k;.
Und die Nutzerinteraktion (Eingabe, Ausgabe) musst du noch machen, den Teil habe ich nicht geschrieben.
 
Neue Frage »
Antworten »


Verwandte Themen

Die Beliebtesten »
Die Größten »
Die Neuesten »