Thema: [C++] Flieskommevariable ohne Rundung
Klicke hier, um dich anzumelden
Du kannst aus dieser Liste ein Symbol für deine Nachricht auswählen.
Wenn du diese Option aktivierst, werden URLs automatisch mit BB-Code ergänzt. www.beispiel.de wird zu [URL]http://www.beispiel.de[/URL].
Wenn du möchtest, kannst du dieses Thema bewerten.
Dies ist ein Aproximationsalgorithmus wenn ich mich recht entsinne. Eigentlich müsste ehr in einer schleife realisiert werden. Bei jedem iterationsschritt nährt sich die zahl etwas mehr der wurzel des eigentlichen wertes an. Das heißt, nach unendlich vielen schritten, ist dieser wert wirklich erreicht. Sowas musste ich glaube ich mal in ada schreiben. Du müsstest es so machen while (alterwert != neuerwert) { alterwert = neuerwert; neuerwert = .... ; } ausgabe(neuerwert) Der witz der sache ist, dass dieser algorithmus terminiert, obwohl er es rein mathematisch nicht machen würde... (weil nämlich irgendwann die selben mantissen im double da stehen) Das problem ist aber allgemein ein ganz anderes. Für dieses Problem gibt es keine exakte lösung. Ich mein, was ist die wurzel aus 2 ? .... naja, was soll das sein, wurzel 2 ist eben eine zahl, jeder versuch die zahl irgendwie aufzuschreiben als 1.4... ist quatsch. irgendwann bricht man die nachkommastellen ab und schon ist der wert ungenau. also folgende sachen zum drüber nachdenken: 1. Eine wurzel aus einer zahl lässt sich mit diesem algorithmus immer nur näherungsweise bestimmen, da der algorithmus erst bei dem unendlichem schritt die richtige lösung bietet. (quasi der limes ist die wurzel) 2. WEurzelberechnungen nie exakt möglich. Schon garnicht im rechner, da eine irrationale zahl nicht wirklich im rechner dargestellt werden kann 3. wichtig für das allgemeine verständnis wär der begriff der unendlichkeit. 4. mit runden hat das ehr garnichts zu tun. die float / double werte sind schon mehr als genug gerundet. Runden ist nur so eine unart, die man in der schule kennen lernt. Schöne Grüße, Marc
Du hast anscheinend recht, das hört sich ziemlich schwierig an! Aber kann mna nicht irgendwie einstellen auf wie viel Zahlen gerundet werden soll ? das würde ich dann in den Dialog einbauen. Ich programmiere an einem Programm um die Wurzel von irrationalen Zahlen nach Heron zu berechnen! Ich bin fertig, nur die Ergebnisse sind immer ungenau, wegen der Rundung bei Float-Werten. Hier mein Source Code: Code: #include <cstdlib> #include <iostream> using namespace std; float berechneheron(float x,float y) { float n=(x+y)/2; float m=2/n; float n2=(n+m)/2; float m2=2/n2; float n3=(n2+m2)/2; float m3=2/n3; /* float n4=(n3+m3)/2; float m4=2/n4; float n5=(n4+m4)/2; float m5=2/n5; float n6=(n5+m5)/2; float m6=2/n6; */ return m3; }; int main(int argc, char *argv[]) { float x; float wurzel; cout << "Bitte geben sie die zu berechnende Wurzel ein:" << endl; cin >> wurzel; cout << "Bitte geben sie einen Startwert (Xo) ein:" << endl; cin >> x; float y=wurzel/x; cout << "Der 3.Naehrungswert von " << wurzel << " (mit Xo: " << x << " Yo: " << y << ") ist "<<berechneheron(x,y)<< "." << endl << endl; system("PAUSE"); return EXIT_SUCCESS; } Sagt mir was ihr von meinem Code haltet!
#include <cstdlib> #include <iostream> using namespace std; float berechneheron(float x,float y) { float n=(x+y)/2; float m=2/n; float n2=(n+m)/2; float m2=2/n2; float n3=(n2+m2)/2; float m3=2/n3; /* float n4=(n3+m3)/2; float m4=2/n4; float n5=(n4+m4)/2; float m5=2/n5; float n6=(n5+m5)/2; float m6=2/n6; */ return m3; }; int main(int argc, char *argv[]) { float x; float wurzel; cout << "Bitte geben sie die zu berechnende Wurzel ein:" << endl; cin >> wurzel; cout << "Bitte geben sie einen Startwert (Xo) ein:" << endl; cin >> x; float y=wurzel/x; cout << "Der 3.Naehrungswert von " << wurzel << " (mit Xo: " << x << " Yo: " << y << ") ist "<<berechneheron(x,y)<< "." << endl << endl; system("PAUSE"); return EXIT_SUCCESS; }
Hallo, das ist ein Thema, welches man garnicht so pauschal beantworten kann. Da aber eine Beantwortung noch nicht erfolgt ist, versuche ich es mal etwas ausführlicher. Ich habe über dieses Thema mal ne ganze Vorlesung gehört ... also es ist wirklich schwierig. Prinzipiell ist es unmöglich eine Fließkommazahl im PC ohne rundung speichern. Das ist auch unabhänig von der Programmiersprache. Um das zu verstehen muss man wissen wie eine Fließkommazahl aufgebaut ist: Fließkommazahklen sind nach IEEE 754 genormt. Eine belibige zahl wird sooft durch 2 geteilt / multipliziert bis der wert zwischen 0 und 1 liegt. Danns chreibt man die zahl wie folgt in den ram: 1 Bit: vorzeichen 8 Bit: Exponent (wie oft man mit zwei multipliziert / geteilt hat) 23 Bit: Mantisse (die zahl zwischen 0 und 1) Und hierraus ergibt sich schon der fehler: Mit der 23 Bit mantisse kann man logischerweise nicht jede reele Zahl zwischen 0 und 1 erreichen die es gibt. Man hat also nur rasterpunkte auf dem Zahlenstrahl. Und wenn man nun eine zahl abspeichern will, die zwischen zwei solchen rasterpunkten liegen, wird einfach ein rasterpunkt genommen, da die korrekte Zahl nicht gespeichert werden kann. Wie genau gerundet wird, und wie lang genau die exponennten und mantissen sind, ist in der spezifikation der einzelnen programmiersprache nachzulesen, bzw. ist wie bei c++ compilerabhänig. Also musste da in der doku des compilers nachlesen. Prinzipiell stehen die zwei typen in c++ zur verfügung. float und double. Float mit einfacher und double mit douppelter genauigkeit. Also, wenn ich mich recht errinere, erfüllt double genau die den IEEE 754 Standard (also die 32 bit kodierung) Es gibt natürlich, wenn du mathematisch begangt bist, die möglichkeit, bestimmte zahlen selber abzuspeichern. Beispielsweise die zahl 0.3333333... also (1/3) geht nicht sinnvoll als double abzuspeichern. irgendwann bricht der periondenbruch ab. Du hast aber die möglichkeit, die zahl als Rational abzuspeichern. Also baust dir eine eigene klasse rational, die nenner und zähler abspeichert. Auf dieser klasse definierst du die üblcihen mathematischen operationen. (also du speicherst die zahl nicht als 0.3333... ab sondern als 1 / 3) Wenn du das sauber machst, kannstze das beispielsweise testen. Dann ist beispielsweise (3 * 1/ 3) wirklich 1, während es bei dem 3* 0.333333 werten (höstwahrscheinlich) 0.9999... wär. Eine anderemöglichkeit wär es, die oben genannte fließkommaumsetzung zu erweitern. Das ist aber relativ schwer. Du kannst ha beispielsweise eine 46 bit mantisse abspeichern. Damit wird natürlich dein raster enger und du bekommst mehr zahlen unter. Dazu musst du dir wieder einen eigenen datentyp bauen und alle operationen darauf dfinieren. Das prioblem ist dabei im allgemeinen, das operationen wie radizieren und logarithmieren sehr schwer zu implementieren sind. Diese haben meist hohren numerischen stellenwert und laufen meist auf aproximationen diverser reihen hinaus. (wie zum beispiel auch PI) Im allgemeinen ist es aber wie gesagt unmöglich alle zahlen abspeichern uzu könne. Der Speicher des rechners ist begrenzt (also endlich) es gibt aber überabzählbar unendlich viele reele (complexe) zahlen. Ach ja, und da währen wir bei letzten Punkt. bei einer neuen implementierung müsstest du ja auch die komplexen zahlen einbinden. Denn ab und zu muss man mal die wurzel aus negativen zahlen ziehen. und das geht ja in den reelen zahlen schlecht. Schöne mathematische Grüße aus Weimar, Marc
Hi, wie kann cih in C++ eine Flieskommazahl so speichern, dass sie nicht gerundet wird, natürlich auch bei der Berechnung! MFG Seppl @Eddie/Alpha: Du hast im Newsletter durchblicken lassen, dass keine Frage unbeantwortet bleibt! Also so maßlos übertreiben würde ich nciht ... Ich hatte schonmal ne Frage über C++ und Linux, die ohne Reaktion alt wurden und mitlerweile Versteinert sind! Wenn man wirklich spezielles Wissen braucht, dann muss man sich für viele Themen ein anderes Forum such, dass sich spezialisitert hat, weil man hier auch viel nciht darf und sich die User eben in den entsp. Gebieten nicht auskenne! Ich schreibe das an diese Stelle, denn du ließt ja eh alle Beiträgee ^^
Foren-Regeln