Das Programm funktioniert soweit gut, bis auf diesen Test. Bis 3^3 wird korrekt „Kubikzahl“ ausgegeben, ab 4^3 nicht mehr. Wenn ich mir die Kubikwurzel ausgeben lasse, sieht sie allerdings immer ganzzahlig aus.
Bei der Quadratzahl-Funktion z.B. gibt es dagegen keine Probleme, sie funktioniert analog mit sqrt(n).
Hat jemand eine Idee, woran das liegen könnte? Ist pow() irgendwie besonders ungenau? Oder habe ich irgendeinen dummen Fehler drin?
zunaechst einmal solltest du dir ueberlegen, wie double’s tatsaechlich funktionieren (z.B. im Wiki), und weshalb es keine exakte Darstellung fuer 1.0/3.0 gibt.
Danach wirst du verstehen, dass dein fmod(n,1.0) nicht immer das liefert, was du haben möchtest.
Es koennte naemlich sein, dass dein "pow(n,1.0/3.0) fuer z.B. 64.0 etwas liefert, was marginal kleiner ist als 4.0, zum Beispiel 3.99999999999999x und dann dein fmod(,1.0) als Resultat dann nicht 0.0 sondern .99999999999999x (Zahlen sind nur Beispiele)
danke für deine Antwort. Hast du vielleicht einen Tipp, wie ich ohne die Ungenauigkeiten rechnen kann? Ich meine, das Gerät heißt Rechner, es wäre schon toll, wenn man damit rechnen könnte
danke für deine Antwort. Hast du vielleicht einen Tipp, wie
ich ohne die Ungenauigkeiten rechnen kann? Ich meine, das
Gerät heißt Rechner, es wäre schon toll, wenn man damit
rechnen könnte
Genau es heisst Rechner und nicht Präzisionsrechner!
Das problem ist, dass ein Präzisionsrechner die erste Berechnung von 1/3 nicht hinaus käme, der würde da in 1000 Jahren noch dran rechnen!
Um also eine endlich Programmlaufzeit zu erhalten, muss man die Präzision immer auf eine bstimmte Stellenzahl begrenzen!
Du solltest dich dringend mit den Basics der Flieskommazahlen-Arithmetik befassen!
danke für deine Antwort. Hast du vielleicht einen Tipp, wie
ich ohne die Ungenauigkeiten rechnen kann? Ich meine, das
Gerät heißt Rechner, es wäre schon toll, wenn man damit
rechnen könnte
ja, wenn es denn so einfach waere … doubles sind oft ungenau, man muss ab und zu runden und kann eigentlich fast nie auf einen konkreten Wert vergleichen.
Allerdings: Wer sagt denn, dass du ueberhaupt doubles nehmen musst.
Aber wieder: Unendlich gross gibt es weder bei double noch anderen Standard C++ Typen (dazu bedarf es dedizierter Libraries und die meisten davon koennen dir auch nicht 1/3 exakt darstellen)
Und da es viele Wege nach Rom gibt, könnte man das 1.0/3.0 auch teilvermeiden, z.B. koennte man 3te_Wurzel_aus_n_ist_ganzzahlig(n) auch fuer positive n wie folgt berechnen.
bool kbwurzel(const double n)
{
const double epsilon = 1E-11;
const double x = floor(exp(log(n)/3.0)+0.5);
return fabs(x\*x\*x - n)
/\* zweites Beispiel hier entfernt \*/
Woher ergibt sich dieser Ansatz: Nun eine Multiplikation laesst sich als eine Addition von Logarithmen darstellen.
Sei hier nun N die Zahl, aus der die Wurzel gezogen werden soll und x die dritte Wurzel.
=\> N = x\*x\*x = exp(log(x)+log(x)+log(x)) = exp(3log(x))
=\> N = exp(3log(x))
=\> log(N) = 3log(x)
=\> log(N)/3 = log(x)
=\> exp(log(N)/3) = x
Der Rest in den Funktionen und das Ausprobieren, ob ich keinen Fehler gemacht habe, ist "left as an exercise to the reader" ...
Gruss
n.