Forum: Compiler & IDEs Genauigkeit von float in AVR-GCC


von Norbert (Gast)


Lesenswert?

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

von Peter (Gast)


Lesenswert?

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

von Norbert (Gast)


Lesenswert?

Also , da ich 6-stellige Genauigkeit brauche, werde ich mich mit
AVR-GCC befassen müssen.

von Dietmar (Gast)


Lesenswert?

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

von Matthias (Gast)


Lesenswert?

Hi

der GCC implementiert nur float auf dem AVR.

Matthias

von RTFM (Gast)


Lesenswert?

RTFM.

von Dietmar (Gast)


Lesenswert?

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

von Matthias (Gast)


Lesenswert?

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

von tex (Gast)


Lesenswert?

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))

von Jörg Wunsch (Gast)


Lesenswert?

> 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.

von T.Stütz (Gast)


Lesenswert?

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

von Jörg Wunsch (Gast)


Lesenswert?

> 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?

von Rufus T. Firefly (Gast)


Lesenswert?

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.

von T.Stütz (Gast)


Lesenswert?

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

von A.K. (Gast)


Lesenswert?

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.

von A.K. (Gast)


Lesenswert?

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).

von Rufus T. Firefly (Gast)


Lesenswert?

@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.

von A.K. (Gast)


Lesenswert?

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. [...]"

von tex (Gast)


Lesenswert?

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.

von Rufus T. Firefly (Gast)


Lesenswert?

@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?

von A.K. (Gast)


Lesenswert?

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.

von Jörg Wunsch (Gast)


Lesenswert?

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.

von A.K. (Gast)


Lesenswert?

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.

von Dietmar (Gast)


Lesenswert?

...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

von Jörg Wunsch (Gast)


Lesenswert?

> 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
Noch kein Account? Hier anmelden.