Meines Wissens ist die Genauigkeit bei float-Berechnungen 6-stellig.(ANSI-C) Mein CodeVison macht nur 5 Stellen. Wie ist die Genauigkeit bei AVR-GCC? Norbert
sizeof() wird es dir verraten ;-) Aber avrgcc kann ja auch double oder long double ... Ich denke mal, da bleiben keine Wünsche mehr offen. Gruss, Peter
Ich konnte bisher nur feststellen, dass die tatsächliche Rechengenaugkeit von double Funktionen im AVR-GCC deutlich schlechter ist als bei wissenschaftlichen Taschenrechnern, was eigentlich nicht sein kann. Die Ergebnisausgabe mit Printf der Beispiele erfolgte über das USART des AVR ATMEGA169. Laut Compiler-Manual wertet Printf %f oder %F double Argumente aus. Beispiel 1: printf("double float %.35F\n", 1.23456789012345678901234567890); hat zum Ergebnis: double float 1.23456788063049316406250000000000000 Das ist definitiv keine Double Rechengenauigkeit sondern eher float. Beispiel 2: printf("double float %.35F\n",1.00000000000001-1); hat zum Ergebnis: double float 0.00000000000000000000000000000000000 Das ist definitiv keine Double Rechengenauigkeit sondern eher float. Aufgefallen sind mir die Fehler, weil andere Berechnungen mit 4 Grundrechenarten in meiner verkehrte Ergebnisse lieferten. Ich habe dann einfachste Rechenfunktionen getestet, um die tatsächliche Rechengenaugkeit zu ermitteln und den Fehler einzukreisen. Hat jemand eine kompetente Antwort, wie man den AVR-GCC-Compiler dazu bringt tatsächlich mit Double Genauigkeit zu rechnen ? Hier noch ein Link auf eine Internetseite fur Floating Point nach IEEE-754: http://www.telecom.fh-htwchur.ch/~zogg/IEEE_754_Umwandlung_Gleitkomma_zu_32_u_64_Bit.htm gruss Dietmar
Nachtrag zu double float: Ich meine, dass ein Compiler die gültige internationle Norm IEEE-754 zwingend als Qualitätsmerkmal einhalten muss: a) "float" hat ein 32bit-Format (4 Byte) mit geringerer numerischer Rechengenauigkeit bei kürzerer Rechenzeit. b) "double" hat ein 64bit-Format (8 Byte) mit höherer numerischer Rechengenauigkeit bei längerer Rechenzeit. Mogeln gilt nicht!!! Wenn ein Compiler "double" mit 64bit nicht kann, darf der Compiler das Schlüsselwort "double" nicht akzeptieren. Wenn der Compiler "double" mit 32bit rechnet, ist das eindeutig nicht normkonform und somit eine "Mogelpackung". Wer trotzdem einen fertigen Sourcecode, der 64bit-"double" enthält und erfordert, auf einen 32bit-"float"-Compiler portieren will, könnte dann nachträglich - aber bewusst und auf eigene Verantwortung - mogeln und ungenauer rechnen: #define double float // z.B. in eigene Projekt-Header-Datei einfügen Damit ersetzt der Compiler global das Wort "double" durch das Wort "float" - wie gesagt alles auf eigene Verantwortung. Klar ist, auf dem AVR-GCC-Compiler braucht man den #define nicht, denn der Compiler mogelt ja von alleine. gruss dietmar
Hi wenn es dich stört: Der Compiler ist Open Source und jeder kann seine Erweiterungen einbringen. Also dann mal ran und die double-Implementierung für den AVRGCC realisiert. Der Mangel einer solchen deutet aber darauf hin das der Bedarf nach double-Genauigkeit auf dem AVR nicht alzu extrem ist. Mir persönlich ist es bis jetzt noch nicht passiert das ich float benötigt hätte ganz zu schweigen von double. Matthias
Hallo Dietmnar. Ich hatte das Probelm auch vor kurzem. Aber es ist tatsächlich so dass gcc die Double zu float macht. (Ohne jedwigen Kommentar (Fluch))
> Ich meine, dass ein Compiler die gültige internationle Norm IEEE-754 > zwingend als Qualitätsmerkmal einhalten muss: Wer sagt das denn? Es steht nirgendwo im Standard, wie die Gleitkommazahlen implementiert codiert sein müssen. Damit ist IEEE-754 außen vor, das beschreibt nämlich eine Codierung. > a) "float" hat ein 32bit-Format (4 Byte) > b) "double" hat ein 64bit-Format (8 Byte) Auch davon steht nichts im C-Standard. Es ist zwar richtig, dass eine 4-Byte-IEEE-Implementierung nicht standardkonform ist, aber bitteschön, die Stelle, an der das steht, darfst du erstmal finden... Mit deinen durch nichts fundierten ad-hoc-Behauptungen, die du hier hingesetzt hast, lass ich dich die Stelle einfach mal selbst suchen. Ich habe mir übrigens sagen lassen, dass es bei C++ sogar vollständig konform wäre (habe das aber noch nicht verifiziert). > Wenn der Compiler "double" mit 32bit rechnet, ist das eindeutig > nicht normkonform und somit eine "Mogelpackung". Du weißt aber, über welche Zielplattform du hier redest und was 64-bit-Gleitkomma auf dieser bedeutet -- einschließlich aller Randbedingungen implicit promotion to double --, ja? Es fällt einem halt hier komplett auf die Füße, dass der C-Standard so unglücklich davon ausgeht, dass jeder Compiler den Typ `double' implementiert, wenn er denn Gleitkomma macht. Andernfalls hätte sicher niemand ein Problem damit gehabt, nur `float' zu implementieren. Selbst der Mercedes unter den Compilern (IAR Embedded Workbench) benutzt standardmäßig 32-bit-Gleitkomma. Allerdings kann man den auf 64 bit umschalten. Für den AVR-GCC müsste sich einfach jemand finden, der das schreibt. Der Haken ist hier die Kompatibilität mit existierendem Code: die Leute gehen davon aus, dass `double' 32 bit ist (weil es bisher so war), den Default dann irgendwann einfach auf 64 bit zu ändern, würde vermutlich einen Aufschrei bringen, weil dann viele existierende Programme gar nicht mehr in die ROMs passen würden... Aber dafür würden wir schon eine Lösung finden, wenn denn jemand die 64-bit-Bibliothek auf den Tisch legt.
K&R-C (also quasi Vorgänger von ANSI-C) aus "Programmieren in C" (ISBN 3-446-13878-1), Seite 11: "Abgesehen von int und float hat C verschiedene andere elementare Datentypen: char ein einzelnes Zeichen short ein kleiner, ganzzahliger Wert long ein großer, ganzzahliger Wert double ein Gleitkomma Wert mit doppelter Genauigkeit" Ich gehe davon aus das ANSI-C das so übernommen hat. Weiß das jemand ? Achtung: Ich stimme zu das für einen uC ein double absoluter Schwachsinn ist, wer wirklich double benötigt sollte sich überlegen gleich einen PC hinzustellen, der Aufwand eine double LIB zu erzeugen ist bei weitem größer als ein billiger 486 (der MatheCoProz intern hat) Gruss
> Ich gehe davon aus das ANSI-C das so übernommen hat. Assumptions are the root of all evil. > Weiß das jemand ? Ja, ich. Hat es natürlich nicht (sonst hätte ich das da oben so nicht geschrieben). Was bitte soll ,,doppelte Genauigkeit'' sein? ±10 µm? ±0,3 K?
T. Stütz zitiert tatsächlich aus der Erstausgabe* des K&R - das ist die so besonders drollig grauenerregend (maschinell?) übersetzte. Einige Zeilen oberhalb der zitierten Stelle steht da übrigens noch dies: "float benötigt 32 Bit, das ergibt etwa 7 signifikante Dezimalziffern, mit einem Wertebereich zwischen etwa 10E-38 und 10E38." Dieser Satz ist allerdings mit äußerster Vorsicht zu genießen, fängt nämlich der unmittelbar davorstehende so an: "Auf der PDP-11 und den Siemens PC's beispielsweise (...)" Das kann nahelegen, daß die Größenangabe sich darauf bezieht, aber das Buch ist generell so grauenerregend schlecht übersetzt, daß man sich allenfalls auf die korrekte Sequenz der Seitenzahlen verlassen kann. Desweiteren wird auf Angaben für andere Systeme an anderen Stellen verwiesen. Im Kapitel 2 (Datentypen), S. 38 heisst es lapidar "float, einfacher Gleitkomma Wert. double, doppelt genauer Gleitkomma Wert." Eine auf S. 196 abgebildete Tabelle erwähnt die Größen verschiedener Datentypen auf unterschiedlichen Maschinen. Mit einer Ausnahme (Honeywell 6000) ist auf allen anderen float 32 Bit und double 64 Bit groß. Die Honeywell-Maschine arbeitet mit 36 und 72 Bits. Die von Jörg bekrittelte Formulierung "doppelte Genauigkeit" enstammt somit wortwörtlich dem K&R. In der zweiten Ausgabe** des K&R, der ANSI-C (C89) beschreibt, steht folgendes im Kapitel 2 (Datentypen), S. 36: "float ein einfach genauer Gleitpunktwert. double ein doppelt genauer Gleitpunktwert." Das stellt, vom korrekteren Deutsch abgesehen, zunächst keine wesentliche inhaltliche Verbesserung dar. Kurz darauf wird auf long double eingegangen und dann folgt der *Kernsatz*: "Wie bei ganzen Zahlen, ist die Größe von Gleitpunktobjekten implementierungabhängig. float, double und long double könnten für eine, zwei oder drei verschiedene Größen stehen." Den letzten Satz nochmal durchlesen! "float, double und long double könnten für eine, zwei oder drei verschiedene Größen stehen." Also: sizeof (float) <= sizeof (double) <= sizeof (long double) (Ja. Ich bin mir im Klaren darüber, daß bei präziser Lesart des bewussten Satzes sogar folgendes legal ist: sizeof (float) >= sizeof (long double) Ich denke aber, mich nicht zu weit aus dem Fenster zu lehnen, wenn ich das für unwahrscheinlichen Schwachsinn halte und daher die "natürlich" erscheinende Reihenfolge annehme.) Das wiederum besagt, daß die vom avr-gcc vorgenommene Annahme sizeof (float) == sizeof (double) vollkommen korrekt ist. *) Kernighan & Ritchie Programmieren in C Deutsche Ausgabe besorgt (sic!) von Prof. Dr. A. T. Schreiner und Dr. Ernst Janich Hanser Verlag, 1983 Die Herausgeber dieses Buchs fanden es schick, Codebeispiele in einer Proportionalschrift zu setzen und verwendeten eine höchst seltsame Interpretation der deutschen Sprache - man ist gewillt, an eine maschinelle Übersetzung zu denken. **) Kernighan & Ritchie Programmieren in C Deutsche Ausgabe besorgt (sic!) von Prof. Dr. A. T. Schreiner und Dr. Ernst Janich Hanser Verlag/Prentice-Hall 1990 ISBN 3-446-15497-3 Hier "besorgten" die Herausgeber es der Sprache nicht mehr; das Buch ist deutlich besser lesbar, in korrektem Deutsch abgefasst und verwendet -wie es sich gehört- eine nichtproportionale Schriftart für Codebeispiele. Offensichtlich sind sogar deutsche Titelträger lernfähig, was wiederum verwundert.
Damit ist meine Frage ausführlichst beantwortet - Danke ! Und: Wir wissen jetzt das es nicht sicher ist das "double" doppelt so genau ist wie "float" sondern nur das es mindestens so genau wie "float" ist. @Jörg Wunsch eine Quellenangabe wäre schön, muß aber nicht sein. PS: Ich will dieses Thema nicht weiter forcieren, wenn also keiner darauf antwortet bin ich auch nicht böse. Gruss
Wenn man schon die Original-Ausgabe von K&R bemüht, dann bitte die echte (Siemens-PC bei K&R'78, also nee...). Und da stand es schon dankenswert deutlich drin: "Single-precision floating point (float) and double-precision floating point (double) may be synonymous in some implementations". Mit einer deutschen Übersetzung kann ich nicht dienen - würde mich interessieren was da aus diesem Satz wurde. > "float ein einfach genauer Gleitpunktwert. > double ein doppelt genauer Gleitpunktwert." > Das stellt, vom korrekteren Deutsch abgesehen, zunächst keine > wesentliche inhaltliche Verbesserung dar. Ist aber die korrekte Übersetzung vom 78-er Original. Allerdings neigen K&R ohnehin dazu, den Begriff "double-precision" als Synonym für "double" zu verwenden. Was Anlass für Irritation geben mag. Und übermässige Präzision hat den Autoren damals ohnehin keiner vorgeworfen. Die Referenz waren eher die Compiler, erst Ritchies PDP-11 Original, dann Johnsons PCC in seinen Varianten. > short ein kleiner, ganzzahliger Wert > long ein großer, ganzzahliger Wert > double ein Gleitkomma Wert mit doppelter Genauigkeit" Das ist schon mal inhaltlich kompletter Unfug. "char", "int", "float" und "double" sind Datentypen, "short" und "long" sind hingegen qualifiers, also eine Art Eingrenzung von Typen, alleinstehend eine Abkürzung von "short int" und "long int". Wenn das tatsächlich direkt aus der deutschen Übersetzung stammt, dann war's schade um den Wald.
Im ANSI C Standard wird es ein bischen genauer: Zwar lässt "There are three floating types, designated as float, double, and long double. The set of values of the type float is a subset of the set of values of the type double; the set of values of the type double is a subset of the set of values of the type long double." noch alles offen, an anderer Stelle wird es jedoch deutlicher, weil als Mindestanforderung an die Genauigkeit gilt: FLT_DIG 6 DBL_DIG 10 LDBL_DIG 10 Und das ist mit 32bit double nicht zu schaffen. Zwar darf also float = double = long double gelten, aber eben nur wenn dabei mindestens 10 Dezimalstellen herauskommen. M.a.W: GCC/WinAVR geht hier konform mit K&R'78, nicht aber mit ANSI'89. Was mich persönlich bei einem 8bit µC freilich nicht stört, mir wäre es sogar lieber wenn die Library wider allen Standards mit sizeof(int)==1 gebaut wäre (erheblich effizienterer Code).
@A.K.: Das erste Zitat (Wortlaut "Gleitpunktwert") enstammt der zweiten Ausgabe des K&R, das zweite, von T. Stütz zitierte (und von Dir inhaltlicher Unfug geziehene) aus der IMHO unsäglichen ersten Ausgabe. Das steht da wortwörtlich so drin! Was die 1983 mit "Siemens-PC" gemeint haben könnte, entzieht sich meiner Kenntnis. Könntest Du mir sagen, aus welchem Kapitel/Abschnitt das von Dir erwähnte englische Zitat aus dem Ur-K&R stammt? Ich könnte dann die "Übersetzung" der entsprechenden Passage aus der deutschen 83er-Ausgabe hier zitieren.
Das "synonymous" Zital entstammt der Reference, Appendix A.4. Und der "Unfug" im Original - Chapter 2.2, Data Types and Sizes: "There are only a few basic data types in C: - char - a single byte [...]. - int - an integer, typically relecting the natural size of integers on the host machine. - float - single-precision floating point. - double - double-precision floating point. In addition, there are a number of qualifiers which can be applied to int's: short, long and unsigned. [...]"
Also mein 15 Jahre alter RC-Compiler für 8031 konnte double und ich hab sie schon gebraucht, nicht oft aber dafür ging es dann nicht ohne, aber ich habe ganz offensichtlich viel Glück gehabt, stelle ich fest.
@A.K. Hier die Übersetzung: K&R 1983, S. 197 (Abschnitt 4 im Anhang A) Gleitkomma Werte einfacher und doppelter Genauigkeit können in einer Implementierung auch identisch repräsentiert sein. Auf den meisten Systemen benötigen double vereinbarte Objekte jedoch doppelt so viel Speicherplatz wie Objekte vom Typ float. Interessant ist übrigens noch Abschnitt 6.2 im Anhang A Gleitkomma Werte verschiedener Genauigkeit Alle Gleitkomme Arithmetik in C erfolgt mit doppelter Genauigkeit; float Werte in Ausdrücken werden in double Werte verwandelt, indem die Mantissen entsprechend mit 0 verlängert werden. Muß ein double Wert, etwa bei einer Zuweisung, in einen float Wert umgewandelt werden, so erfolgt eine Rundung, bevor die Mantisse entsprechend abgebrochen wird. Der "Unfug" übrigens ist nicht die Übersetzung von Kapitel 2.2, sondern von Kapitel 1.2 (Variablen und Arithmetik). Wie sieht das im Original aus?
Naja, was ich halt über die Präzision von K&R so schrieb... C provides several other basic data types besides int and float: [...] - short - short integer - long - long integer [...] Das Original ist an dieser Stelle also inhaltlich genauso falsch wie die Übersetzung und in sich selbst widersprüchlich. Was ist an 6.2 bemerkenswert? Interessanter finde ich (vom Thema etwas abweichend) 6.5. Das ist nämlich ein subtiler Unterschied zwischen K&R und ANSI: K&R behält die "unsigned" Eigenschaft immer bei, ANSI hingegen nur wenn's nicht anders geht.
Der virtuelle Preis geht an AK fürs Finden der Stelle, in der das im Standard steht. Wie gesagt, mir hat jemand glaubhaft versichert, dass der C++-Standard selbst das nicht enthält.
Na, bei soviel Lob werd ich gleich mal weitersuchen. > Ich habe mir übrigens sagen lassen, > dass es bei C++ sogar vollständig konform wäre Stroustrups Original von 1990, also vor ANSI C++ aber nach ANSI, schreibt exakt das gleiche wie ANSI C, also 6/10 Dezimalstellen als Mindestanforderung via float.h. Allerdings einschränkend mit der Bemerkung "An implementation that provides functionality consistent with ANSI C will define ..." - man kann also machen was man will, ist aber schön blöd wenn sich nicht an ANSI C hält. ANSI C++ wiederum enthält sich konsequenterweise einer eigenen Meinung und verweist direkt auf ANSI C, verschönert via Templates. Einen Unterschied zwischen C++ und C gibt's freilich doch: Stroustrup erlaubt Berechnung in "float" Genauigkeit, während ANSI C immer in "double" rechnet.
...eine großartige Resonanz. Ich bin kein Informatiker. Nach meiner Kenntnis entstand die Floating Point Zahlendarstellung IEEE754 unabhängig von Programmiersprachen und hat keine Hardwarebindung. IEEE754 ist mir von C-, (Turbo-)Pascal-, Delphi, Basic-Compilern, Java... im µC-Bereich und im PC-Bereich auf den zahllosen Internetseiten und bereits vor 10-15 Jahren in Compilerhandbüchern begegnet. Der Erfinder des Computers Konrad Zuse erfand auch die Grundlagen der noch nicht genormten Floating Point Zahlendarstellung, die auf Großrechnern, Homecomputern und wissenschaftlichen Taschenrechnern programmiert wurden. Daraus entstand die erste normierte IEEE754 nach meiner Kenntnis um 1980 herum: Durch die Normierungs-Stelle des Amerikanischen Elektroingenieur-Verbandes wurde ca.1980 die Norm IEEE754 für die Darstellung von Gleitkomma-Zahlen festgelegt. Somit ist der Ursprung viel älter als so manche Programiersprache. IBM, Intel, Texas Instruments (Erfinder des µP), Bill Gates, Apple, Commodore hätten bestimmt auch eine Antwort dazu. Die Norm IEEE754 gilt für PC-Prozessoren bis heute. gruss Dietmar
> Einen Unterschied zwischen C++ und C gibt's freilich doch: > Stroustrup erlaubt Berechnung in "float" Genauigkeit, während ANSI C > immer in "double" rechnet. Genau das ist aber das wesentliche Argument, warum man in einer Umgebung wie dem AVR "double" nicht als default haben möchte. Gesetzt den Fall, wir hätte mal irgendwann eine 64-bit-FP- Implementierung (der Compiler konfiguriert das ja weitgehend von selbst, aber die Supportbibliothek dafür muss geschrieben werden), dann fände ich es persönlich deutlich sinnvoller, den Typ "long double" für die 64-bit-Arithmetik zu nehmen. Leider verletzt das den Standard, s.o. Was wir daher wahrscheinlich in diesem Fall machen werden (so meine Strategie, falls sich jemand dieser Dinge annehmen möchte :) ist, eine Compileroption ähnlich -mint8 zu machen (vielleicht -mdouble32), die das jetzige Verhalten bewirkt (und die auch wenigstens übergangsweise standardmäßig in den Makefiles drin ist, damit die Quellcode- Kompatibilität gewährleistet wird). long double wäre auch dann 64 bit (man verliert die Möglichkeit also nicht). Anders als -mint8 ist das durchaus eine sinnvolle Option: der Wertebereich von 8-bit Integer Typen ist so gering, dass sich weite Teile der Standardbibliothek damit gar nicht compilieren lassen. Daher ist es praktisch beinahe unmöglich, eine zu -mint8 kompatible Bibliothek überhaupt zu bauen, was den Wert dieser Compileroption drastisch einschränkt. Mit -mdouble32 hat man hingegen nach wir vor alle Möglichkeiten der Bibliothek, nur eben mit reduzierter numerischer Präzision.
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.