Gute Tag! Zu folgender Frage hoffe ich hier auf Hilfe. Stand der Dinge: Ich habe mir ein eigentlich sehr einfaches aber mit der Zeit doch gewachsenes Programm zur Steuerung meines Helikopters geschrieben. Die Befehle werden in Sequenzen abgelegt, welche ein hohes Maß an Berechnungen mit Gleitkommazahlen benötigen, welche dann einfach auf einer SD-Card gespeichert werden. Festpunktrechnung ist hier nicht möglich. Idee: Da die Rechenzeit auf dem ja für Gleitkommaberechnung nicht sehr geeigneten Atmega328 nun doch schon etwas länger dauern, wollte ich diese einfach auf dem PC berechnen lassen und die fertig berechneten Daten auf die SD-Card speichern. Verwendet habe ich hierzu den GCC für Windows. Problemstellung: Die Ergebnisse der Berechnungen mit exakt dem selben C++ Code auf dem PC/GCC unterscheiden sich signifikant von jenen, welche direkt auf dem Atmel berechnet wurden. Es scheint, als wären die Berechnungen auf dem PC wesentlich genauer, was aber nicht gewünscht ist, da der Atmel mit den auf dem PC vorausberechneten Zwischenwerten, auf seine "ungenaue Art und Weise" weiter rechnen muss. Letztlich nun meine Frage: Wie lässt sich auf dem PC die Art und Weise, wie der Atmel die Berechnungen durchführt, simulieren? So, dass beide Ergebnisse, von PC und vom Atmel, exakt übereinstimmen? Leider finde ich hierzu nichts in Google. Freue mich auf Hilfe und danke im Voraus.
Die Numerik lässt grüßen, würde ich behaupten. Du rechnest ja einmal auf einer 8 bit Maschine und dann auf einer 32 oder 64 bit Maschine. Wie gravierend sind denn die Unterschiede? Nicht das es doch an deinem Programm liegt.
Ein Standard-Test für Gleitkommarechnungen ist: e^pi-pi und dann das Ergebnis mit 20 vergleichen.
rechnest du mit double? Denn im Atmel ist double = float und damit recht ungenau. Im PC nicht.
Danke, bis hier her! Und danke für den Test, aber die Abweichung ist ja bereits bewiesen. Ich rechne nur mit Float, kein Double. Ich denke, dass es das ist, was Max schreibt 8bit gegen 64bit. Die Abweichungen sind nicht groß aber leider zu groß. Gibt es einen Compiler switch den ich übersehen habe, damit der GCC auf dem PC ebenfalls mit 8bit Logik kompiliert? Kann man man eventuell WINAVR irgendwie dazu bewegen, ein kleines Programm mit 8bit Logik für den PC zu kompilieren?
Du mußt auf dem PC alle Rechnungen als float machen, dann sollte das gleiche rauskommen, wie auf dem MC. Also auch alle Zwischenergebnisse wieder als volatile float speichern.
Robert schrieb: > Ich denke, dass es das ist, was Max schreibt 8bit gegen 64bit nein das ist Unsinn. Man kann auch auf einem 8bit System mit 64bit variablen rechnen. Es muss dort genau das gleiche rauskommen.
Und nur zur Verdeutlichung. Mit float (4 Byte) hast du so um die 5 bis 6 signifikante Stellen. Mit double (8 Byte) sind es aber bereits deren 14 bis 15. signifikante Stellen sind nicht dasselbe wie Nachkommastellen! signifikante Stellen sind alle Stellen zusammen. Hast du also die Zahl 1234.567 dann ist nach der 2.ten Nachkommastelle Schluss. Du hast 4 Stellen vor dem Komma, d.h um auf 6 signifikante Stellen zu kommen kannst du noch 2 Nachkommastellen mit dazu nehmen. Alles dahinter (also die 7) ist mehr oder weniger gelogen. Und je mehr du dann mit den Zahlen rechnest und sie weiter bearbeitest, desto schlimmer wird es. Kleine Fehler, die sich aus der nicht Darstellbarkeit der korrekten Zahl ergeben, summieren sich auf und haben die Tendenz erst mal eher klein zu bleiben ehe sie dann recht schnell anwachsen. D.h. nach ein paar Berechnungen hast du keine 5 oder 6 signifikanten Stellen mehr sondern nur noch 4 bis 5. Daher auch der große Unterschied zu double (auch wenn das Problem dort im Grund nicht anders ist). Es macht eben einen UNterschied, ob ich nach 20 Berechnungen nur noch 4 signifikante Stellen (vertrauenswürdige Stellen) habe, oder deren 14.
Robert schrieb: > Ich denke, dass es das ist, was Max schreibt 8bit gegen 64bit. Die > Abweichungen sind nicht groß aber leider zu groß. 8Bit-Float gibts nich so wirklich... Vermutlich hast du mit "int" und "short" etc. gerechnet, was am PC eine andere Größe als am AVR hat. Verwende Typen wie uint16_t aus der <cstdint>. nicht "Gast" schrieb: > Ein Standard-Test für Gleitkommarechnungen ist: e^pi-pi und dann > das > Ergebnis mit 20 vergleichen. ehehehe... http://xkcd.com/217/
Robert schrieb: > Ich rechne nur mit Float, kein Double. Du schon, aber der Prozessor in deinem PC nicht. Der rechnet trotzdem mit sehr viel mehr Bits, und daher kommen wohl die Unterschiede. Es gibt die Compileroption -mpc32. Vielleicht hilft das, ich habs aber nie ausprobiert. Oliver
nicht "Gast" schrieb: > Ein Standard-Test für Gleitkommarechnungen ist: e^pi-pi und dann das > Ergebnis mit 20 vergleichen. Was sagt das Ergebnis 19,99909998 aus?
Oliver schrieb: > Du schon, aber der Prozessor in deinem PC nicht. das spielt keine rolle. Wenn man float will, dann wird die Rechnung auch in float gemacht, egal wie die CPU intern rechnet.
Peter II schrieb: > das spielt keine rolle. Wenn man float will, dann wird die Rechnung auch > in float gemacht, egal wie die CPU intern rechnet. Das kommt zum Teil aber auch darauf an, wie die Berechnung niedergeschrieben wurde. Ob der COmpiler alle Zwischenergebnisse aus der 80 Bit FPU holt und erst mal wieder auf 32 Bit Floats zurechtstutzt, ehe dann damit weiter gerechnet wird, oder ob er das nicht tut und erst das Endergebnis aus der FPU von 80 Bit auf 32 Bit reduziert um es dann in einem float zu speichern.
Karl Heinz Buchegger schrieb: > Das kommt zum Teil aber auch darauf an, wie die Berechnung > niedergeschrieben wurde. Ob der COmpiler alle Zwischenergebnisse aus der > 80 Bit FPU holt und erst mal wieder auf 32 Bit Floats zurechtstutzt, ehe > dann damit weiter gerechnet wird, oder ob er das nicht tut und erst das > Endergebnis aus der FPU von 80 Bit auf 32 Bit reduziert um es dann in > einem float zu speichern. sicher? Ich hätte vermutet das er immer das Zwischenergebnis auf float casten muss. Weil sonst je nach cpu etwas anderes rauskommt.
Robert schrieb: > Festpunktrechnung ist hier nicht möglich. Festpunktrechnung ist immer moeglich, zur Not halt mit wechselnden Bereichen. > Es scheint, als wären die Berechnungen auf dem > PC wesentlich genauer, was aber nicht gewünscht ist, da der Atmel mit > den auf dem PC vorausberechneten Zwischenwerten, auf seine "ungenaue Art > und Weise" weiter rechnen muss. Wenn du ein Problem mit zu genauen Ergebnissen hast, hast du grossen Murks produziert. Mir entsteht der Eindruck, du hast deine Algorithmen schon lange nicht mehr im Griff und deswegen schmeisst dich jede Abweichung aus der Bahn. Aber gut, wenn du den Murks unbedingt brauchst: Mach die Vorbereitung der SD-Karte halt auf einem zweiten AVR.
Peter II schrieb: > sicher? Ich hätte vermutet das er immer das Zwischenergebnis auf float > casten muss. Weil sonst je nach cpu etwas anderes rauskommt. Kommt es ja auch, daher das Problem des TO. Lies dir spaßeshalber mal diese Seite durch: http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86_002d64-Options.html und überlege, warum es da ein paar hilfreiche Compileroptionen zu dem Thema gibt. Oliver
Peter II schrieb: > sicher? Ich hätte vermutet das er immer das Zwischenergebnis auf float > casten muss. Weil sonst je nach cpu etwas anderes rauskommt. Ich hab da jetzt ehrlich gesagt schon lange nicht mehr im Standard nachgesehen. Würde mich aber wundern, wenn sich da etwas grundlegendes geändert hätte: Da im Standard nicht definiert wird, wie Floating Point Arithmetik zu funktionieren hat und schon gar nicht welches System zu benutzen ist, denke ich: ja - das ist so. Da kommt auf jeder FPU etwas anderes raus, je nachdem wie die FPU tatsächlich arbeitet. Das war zb mit dem Microsoft Compiler (früher, heute weiß ich es nicht) ein mögliches Problem, als die FPU's noch nicht sehr verbreitet waren. Je nachdem, ob man eine FPU hatte oder nicht, kriegte man leicht unterschiedliche Ergebnisse. Da man aber Floating Point rechnen sowieso nie ohne ein ausreichend bemessenes Epsilon macht, war das dann so tragisch auch wieder nicht, ob sich die Ergebnisse in der 14.ten signifikanten Stelle unterschieden oder nicht. Gerade bei CAD Sachen sind derartige Dinge unangenehm: Gibt es noch einen schleifenden Schnitt, oder sind 2 Gerade parallel? Liegt der Punkt in einer Ebene oder doch schon darüber oder darunter? Sind 2 Punkte tatsächlich identisch, etc.
Robert schrieb: > Wie lässt sich auf dem PC die Art und Weise, wie der Atmel die > Berechnungen durchführt, simulieren? Anstatt "Atmel" meinst du wohl "avr-gcc"? Letzterer verwendet für solche Berechnungen zur Compilezeit MPFR: "The MPFR library is a C library for multiple-precision floating-point computations with correct rounding." http://www.mpfr.org Falls dein Programm nicht funktioniert, falls Berechnungen zu genau sind, hast du m.E. ein ganz anderes Problem.
Bei einem PC lässt sich die größere Genauigkeit fast nicht vermeiden - klingt komisch - ist aber so. Da es heute praktisch keinen PC ohne FPU mehr gibt, der Compiler dies auch weiß, wird oft darauf optimiert. D.H. auch wenn die Übergabe in kürzerem Format erfolgt, so wird intern oft mit 80 Bit gerechnet. Bleibt ein unnötiges Zwischenergebnis in der FPU, so erfolgen zwei aufeinander folgende Rechnungen u.U. mit 80 Bit ohne zwischenzeitliche Rückkonvertierung. Das aber geht nicht ohne eine erhöhte Genauigkeit.
nicht "Gast" schrieb: > e^pi-pi und dann das > Ergebnis mit 20 vergleichen Scherzkeks. http://xkcd.com/217/
Nicolas S. schrieb: > nicht "Gast" schrieb: >> e^pi-pi und dann das >> Ergebnis mit 20 vergleichen > > Scherzkeks. http://xkcd.com/217/ Spielverderber.
Zunächst vielen Dank, dass Sie alle Sich heute meinen Kopf zerbrochen und meine Befürchtungen, dass es von der Hardware abhängt, bestätigt haben. Ich werde mir die von Johann L. empfohlene MPFR lib ansehen. Wenn ich richtig verstehe, bildet die lib Fließkommaberechnung in Software ab, was dann eigentlich zu Plattform unabhängig gleichen Ergebnissen führen sollte. Ist dies so, wäre meine Frage beantwortet.
Peter II schrieb: > Karl Heinz Buchegger schrieb: >> Das kommt zum Teil aber auch darauf an, wie die Berechnung >> niedergeschrieben wurde. Ob der COmpiler alle Zwischenergebnisse aus der >> 80 Bit FPU holt und erst mal wieder auf 32 Bit Floats zurechtstutzt, ehe >> dann damit weiter gerechnet wird, oder ob er das nicht tut und erst das >> Endergebnis aus der FPU von 80 Bit auf 32 Bit reduziert um es dann in >> einem float zu speichern. > > sicher? Ich hätte vermutet das er immer das Zwischenergebnis auf float > casten muss. Weil sonst je nach cpu etwas anderes rauskommt. Ja, aber das wäre auch ein großer Performance-Verlust, weil dazu der Wert nach jeder Teilrechnung erst in den Speicher geschrieben und wieder gelesen werden muss. Mit entsprechenden GCC-Optionen kann man aber dafür sorgen, daß das tatsächlich getan wird. Aus der GCC-Doku: ********************************************************************** -ffloat-store Do not store floating-point variables in registers, and inhibit other options that might change whether a floating-point value is taken from a register or memory. This option prevents undesirable excess precision on machines such as the 68000 where the floating registers (of the 68881) keep more precision than a double is supposed to have. Similarly for the x86 architecture. For most programs, the excess precision does only good, but a few programs rely on the precise definition of IEEE floating point. Use -ffloat-store for such programs, after modifying them to store all pertinent intermediate computations into variables. **********************************************************************
Robert schrieb: > Die > Befehle werden in Sequenzen abgelegt, welche ein hohes Maß an > Berechnungen mit Gleitkommazahlen benötigen, [...] Kannst Du mal ein Beispiel nennen? Ich kann mir beim besten Willen nicht vorstellen, wo und warum Du Gleitkommazahlen brauchst.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.