epsilon unsichtbar?
-
Hallo.
Mein Programm berechnet Ebenen und aus diesen Geraden und daraus Punkte die wiederum Ebenen bilden ... usw.
Jedenfalls berechne ich nach meist sehr langer Rechnung neue Punkte. Und bilde daraus eine Ebene, "coute" sie, dann hat die Ebene an Stellen sehr kleine Zahlen (leider 4-8x grösser als numeric_limits<T>::epsilon() ), an denen eine 0 sein müsste!!! (-> RECHENFEHLER + BUG
)
Wenn ich jedoch meine vorher berechneten Punkte in eine Datei schreibe und sie neu einlese tritt das nicht auf.Nun meine Theorie
:
Die Punkte haben viel mehr Stellen als sie in der Konsole angezeigt bzw. in der Datei gespeichert werden. Lieg ich da richtig? Kann ich die irgendwie "abschneiden"? Oder sollte ich nochmal Ursachenforschung betreiben
Tyvm
-
Versteht irgendwer den ganzen Text?
-
Ja. Er hat ein Rundungsproblem mit Gleitkommazahlen.
Vermutlich speichert er die Werte in einer Textdatei, beim Einlesen und dann
in eine double konvertieren sind die Krümel halt weg.Ich würde die Genauigkeit begrenzen:
if (wert < 0.0001) wert = 0.0;
-
Scheppertreiber schrieb:
Ja. Er hat ein Rundungsproblem mit Gleitkommazahlen.
Vermutlich speichert er die Werte in einer Textdatei, beim Einlesen und dann
in eine double konvertieren sind die Krümel halt weg.Ich würde die Genauigkeit begrenzen:
if (wert < 0.0001) wert = 0.0;Ja also scheinbar kann man den Text verstehen...
Dein if Funktioniert ja jetzt nur mit Nullen, aber kann ich auch die "Krümel" von beliebigen Zahlen entfernen?

-
eps schrieb:
Dein if Funktioniert ja jetzt nur mit Nullen, aber kann ich auch die "Krümel" von beliebigen Zahlen entfernen?

denke schon, was auch immer Krümel hier sind.
-
klar schrieb:
eps schrieb:
Dein if Funktioniert ja jetzt nur mit Nullen, aber kann ich auch die "Krümel" von beliebigen Zahlen entfernen?

denke schon, was auch immer Krümel hier sind.
asozial?
-
Meine Güte was ist hier denn los?!

Also ich habe eine beliebige Zahl (float).
float a; /* rechnung mit a ... */Wenn ich a in eine Datei schreibe und dann wieder einlese bekomme ich eine minimal andere Zahl . Sie weicht um ca
std::numeric_limits<float>::epsilon()von a ab. Das wird jedoch nicht sichtbar wenn ich beide Zahlen ( a und das wieder eingelesene a ) in der Konsole ausgebe. Dort sehen sie gleich aus.
Einfacher Satz und einfache Frage: Stimmt das und wie kann ich das verhindern?
VIELEN DANK

-
Du meinst einfach, dass eine Zahl 3.5 "plötzlich" 3.499999999999999999 ist, richtig? Und du würdest gerne exakt die Zahl haben, die du mal gespeichert hast. Bei Fließkommazahlen ist das so eine Sache, durch die interne Darstellung von Nachkommastellen gibt es da keine hundertprozentige Genauigkeit. Damit muss man leben (ist normalerweise auch kein Thema, damit rechnen funktioniert wunderbar). Wenn du deine Zahl dann am Bildschirm ausgeben willst, dann runde sie einfach, und gut is!
-
_matze schrieb:
Du meinst einfach, dass eine Zahl 3.5 "plötzlich" 3.499999999999999999 ist, richtig? Und du würdest gerne exakt die Zahl haben, die du mal gespeichert hast. Bei Fließkommazahlen ist das so eine Sache, durch die interne Darstellung von Nachkommastellen gibt es da keine hundertprozentige Genauigkeit. Damit muss man leben (ist normalerweise auch kein Thema, damit rechnen funktioniert wunderbar). Wenn du deine Zahl dann am Bildschirm ausgeben willst, dann runde sie einfach, und gut is!
Die Zahlen sehen ja ausgegeben identisch aus. Mal ein beispeil:
Ich habe 3 Punkte:
(2.97906/0.327357/5.90346)
(2.97906/0.825969/5.90346)
(2.97906/0.00270605/7.52671)Einmal aus der Datei gelesen (A) und einmal auf die ein oder andere weise berechnet (B).
(A) und (B) sehen auf dem Bildschirm absolut identisch aus.
Wenn ich mit (A) rechne bekomme ich folgende Ebene:
0.809372x + 0y + -0z + -2.41117
und mit (B) bekomme ich sowas:
0.809371x + 3.87013e-07y + 7.74029e-08z + -2.41117Eigendlich recht winzige Abweichungen, die aber massiven Einfluss auf weitere Rechnung nehmen ... schon im nächsten Schritt komme ich auf völlig verschiedene Werte...
Einfach ein größeres Epsilon festzulegen funktioniert in anderen Fällen dann jedoch nicht mehr ...
Ich denke dass (A) und (B) doch nicht identisch sind auch wenn sie ausgegeben gleich aussehen... oder wie soll ich sonst auf verschiedene Ebenen kommen?

-
Wenn dir float nicht genau genug ist, musst du wohl auf einen anderen Typen eingehen, wie z.B einer Bigint Klasse, oder so, die eine (fast) beliebige Genauigkeit anbietet.
z.B hier:
http://sourceforge.net/projects/cpp-bigint/
-
klarox schrieb:
klar schrieb:
eps schrieb:
Dein if Funktioniert ja jetzt nur mit Nullen, aber kann ich auch die "Krümel" von beliebigen Zahlen entfernen?

denke schon, was auch immer Krümel hier sind.
asozial?
Nur ein bisschen gemein, aber du siehst ja, keiner versteht ihn so richtig.

-
drakon schrieb:
Wenn dir float nicht genau genug ist, musst du wohl auf einen anderen Typen eingehen, wie z.B einer Bigint Klasse, oder so, die eine (fast) beliebige Genauigkeit anbietet.
z.B hier:
http://sourceforge.net/projects/cpp-bigint/Klingt logisch, ja ... werde mich mal damit befassen
Ty
-
drakon schrieb:
Wenn dir float nicht genau genug ist, musst du wohl auf einen anderen Typen eingehen, wie z.B einer Bigint Klasse, oder so, die eine (fast) beliebige Genauigkeit anbietet.
z.B hier:
http://sourceforge.net/projects/cpp-bigint/Da er aber mit Gleitkommazahlen arbeiten will, hilft ein BigInt wenig.
Eher trifft es hier gmp:
http://www.gmplib.org
Library for arithmetic on arbitrary precision integers, rational numbers, and floating-point numbers// vllt. ist ja auch gleich das hier interessant:
http://www.cgal.org/
-
klar schrieb:
klarox schrieb:
klar schrieb:
eps schrieb:
Dein if Funktioniert ja jetzt nur mit Nullen, aber kann ich auch die "Krümel" von beliebigen Zahlen entfernen?

denke schon, was auch immer Krümel hier sind.
asozial?
Nur ein bisschen gemein, aber du siehst ja, keiner versteht ihn so richtig.

Faszinierend!

-
franz schrieb:
drakon schrieb:
Wenn dir float nicht genau genug ist, musst du wohl auf einen anderen Typen eingehen, wie z.B einer Bigint Klasse, oder so, die eine (fast) beliebige Genauigkeit anbietet.
z.B hier:
http://sourceforge.net/projects/cpp-bigint/Da er aber mit Gleitkommazahlen arbeiten will, hilft ein BigInt wenig.
Eher trifft es hier gmp:
http://www.gmplib.org
Library for arithmetic on arbitrary precision integers, rational numbers, and floating-point numbersJa die kenn ich sogar. Meint ihr es reicht wenn ich meine Punkte "lokal" für die Rechnungen in genauere Typen konvertiere und dann wieder zurück, oder muss ich nu alles umschreiben??

-
Was hilft es dir, wenn du lokal (wenn die Werte schon gegeben sind, berechnet oder aus der Datei gelesen) genauer rechnest, dein Problem aber ist, dass die Konvertierung float -> string -> float verlustbehaftet ist?
Ich kann mir kaum vorstellen, dass man bei komplizierten Gleitkomma-operationen lange ohne Vergleiche mit einem Epsilon auskommt. Der Verlust der Konvertierung ist natürlich ärgerlich (du könntest auch binär rausschreiben oder mit größerer Genauigkeit, damit sich die Fehler in Grenzen halten), aber über kurz oder lang wirst du sowieso Abweichungen haben, die theoretisch nicht sein sollten. Für solche Grenzfälle müssen dann Sonderbehandlungen eingeführt werden, die mit gut gewählten Epsilon-Werten arbeiten.
Wenn Abweichungen von einem solch kleinen Espilon bei dir aber schon zu katastrophalen Veränderungen führen, solltest du evtl. überlegen auf numerisch stabilere Algorithmen und Darstellungsweisen umzusteigen.
-
Decimad schrieb:
Was hilft es dir, wenn du lokal (wenn die Werte schon gegeben sind, berechnet oder aus der Datei gelesen) genauer rechnest, dein Problem aber ist, dass die Konvertierung float -> string -> float verlustbehaftet ist?
Ich kann mir kaum vorstellen, dass man bei komplizierten Gleitkomma-operationen lange ohne Vergleiche mit einem Epsilon auskommt. Der Verlust der Konvertierung ist natürlich ärgerlich (du könntest auch binär rausschreiben oder mit größerer Genauigkeit, damit sich die Fehler in Grenzen halten), aber über kurz oder lang wirst du sowieso Abweichungen haben, die theoretisch nicht sein sollten. Für solche Grenzfälle müssen dann Sonderfälle eingeführt werden, die mit gut gewählten Epsilon-Werten arbeiten.Ich dachte dass dann zB die Abweichung im Beispiel mit den Ebenen so klein werden dass sie keine Rolle mehr spielen. Um die Konvertierung in strings komme ich nicht herum. Das zeug muss in einer lesbaren datei stehen ...
Bin jetzt ein bisschen ratlos

-
Die meisten CPUs rechnen intern so genau, dass der Rechenfehler kleiner ist, als was durch float oder double unterscheidbar wäre. Wobei sich die Fehler in dem Fall natürlich aufsummieren. Darf ich Fragen, was du berechnest und wo diese Ungenauigkeiten zu katastrophalen Veränderungen des Ergebnisses führen?
-
franz schrieb:
Da er aber mit Gleitkommazahlen arbeiten will, hilft ein BigInt wenig.
Eher trifft es hier gmp:
http://www.gmplib.org
Library for arithmetic on arbitrary precision integers, rational numbers, and floating-point numbersJop. Ich wusste nicht mehr, welche Bibliothek es genau ist,welche auch immer empfohlen wird darum habe ich einfach mal das erste bei google als Beispiel genommen.
-
Decimad schrieb:
Die meisten CPUs rechnen intern so genau, dass der Rechenfehler kleiner ist, als was durch float oder double unterscheidbar wäre. Wobei sich die Fehler in dem Fall natürlich aufsummieren. Darf ich Fragen, was du berechnest und wo diese Ungenauigkeiten zu katastrophalen Veränderungen des Ergebnisses führen?
Es kann durchaus sein, dass die Ungenaugkeit sich schnell aufstaut und dann zu unverantwortlichen Fehlern führen. Das ist natürlich vom Kontext abhängig und manchmal auch nicht durch einen anderen Datentypen lösbar. (z.B Matrizenberechnungen) Da müssen dann anderen Wege gefunden werden, um die Ungenaugkeit auszugleichen..
-
drakon schrieb:
Decimad schrieb:
Die meisten CPUs rechnen intern so genau, dass der Rechenfehler kleiner ist, als was durch float oder double unterscheidbar wäre. Wobei sich die Fehler in dem Fall natürlich aufsummieren. Darf ich Fragen, was du berechnest und wo diese Ungenauigkeiten zu katastrophalen Veränderungen des Ergebnisses führen?
Es kann durchaus sein, dass die Ungenaugkeit sich schnell aufstaut und dann zu unverantwortlichen Fehlern führen. Das ist natürlich vom Kontext abhängig und manchmal auch nicht durch einen anderen Datentypen lösbar. (z.B Matrizenberechnungen) Da müssen dann anderen Wege gefunden werden, um die Ungenaugkeit auszugleichen..
Ja genau und wie ich versucht habe zu verdeutlichen sind die Rechnungen die zu den Punkten führen sehr sehr lang ... das erklärt auch warum das grundsätzlich immer auftritt, wenn das Programm schon ne weile läuft.
Ich hab jetzt testweise meine Zwischenergbnisse in dateien geschrieben und sofort wieder eingelesen, weil: Es macht keinen Sinn dass das Programm andere Ergebnisse liefert wenn man abspeichert und später weitermacht...
Wie wäre es eleganter (und vor allem schneller/sicherer) als in dateien zu schreiben? Etwa in std::string zwischenspeichern

Und was noch wichtiger ist: Ist die Genauigkeitsverlust bei der Konvertierung in binäre Dateiformate identisch?
