mikrocontroller.net

Forum: Compiler & IDEs Rundung bei Addition und Multiplikation - Warum?


Autor: Nino K. (lnino)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi an alle.

Ich arbeite mit einem atxmgea und dem AVR Studio.

Dabei ermittle ich 2 Werte welche ich anschließend miteinander addiere.
Bei der Addition wird aber auf 2 Stellen gerundet und ich verstehe nicht 
warum.

Eingaben lauten:

vop2E=1
vop2Z=2
vop2H=3
vop2T=4
vop2ZT=5

nop2E=6
nop2Z=7
nop2H=8

Hier der grundlegende Aufbau Teil1:

  vop2E = vop2E*1;
  vop2Z = vop2Z*10;
  vop2H = vop2H*100;
  vop2T = vop2T*1000;
  vop2ZT = vop2ZT*10000;

  vop2_sum = vop2E + vop2Z + vop2H + vop2T + vop2ZT;

Hier der grundlegende Aufbau Teil2:

  nop2E = nop2E*1;
  nop2Z = nop2Z*10;
  nop2H = nop2H*100;

  nop2_sum = nop2E + nop2Z + nop2H;

  while(nop2_sum>=1)
  {
    nop2_sum=nop2_sum/10;
  }

Und hier scheint der Fehler zu passieren:

op2_sum = vop2_sum + nop2_sum;

Vielleicht kann mir jemand sagen warum hier dieser Rundungsfehler 
passiert.

Ich habe die Tabelle mit den Variablenwerten aus dem AVR Studio 
angehängt, damit ihr seht welche Variable welchen Wert hat.

MUTLIPLIKATION:

Hier ist mir noch etwas aufgefallen:

Wenn ich 2 Variablen multipliziere, dann wird auch stark gerundet:

op1_sum = 48251,172
op2_sum = 63279,938
result = op1_sum * op2_sum;

Dies ergibt laut AVR Studio: 3.0533312E+009
Sollte aber laut Windows calc: 3053331076,084992

Bin froh um jede Hilfe.

Vielen Dank.

: Verschoben durch Admin
Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wieviele Stellen erwartest du von 32-Bit Fliesskommarechnung? avr-gcc 
hat keine echten "double" Werte, kennt nur 32-Bit Format. Und das ist 
gut für ca. 7 Stellen.

Autor: Maxx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dei Datentypen sind double. in 52bit Mantisse sollten mehr Stellen 
reinpassen (es sind im Beispiel 24 signifikante Bits nach der 1, auch 
zuviel für ein single)

Da aber die Rechnung fehlt, ist nicht auszuschliessen, dass 
zwischendurch in single arithmetik was gemacht wurde ...

Autor: Nino K. (lnino)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die Antworten.

@ Maxx: Welche Rechnung meinst du, die fehlen soll?

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zeig doch einfach dein Programm als Dateianhang.

Autor: Maxx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja die eigentliche Rechnung hast du nicht angegeben. Nur beschrieben 
was du machst, ohne den Code dazu.

Man kann einige Dinge ("Fehler") machen, die den numerischen Fehler 
unnötig erhöhen.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Er hat doch alles angegeben, es geht um
   op2_sum = vop2_sum + nop2_sum
und erwartet mehr als 2 Stellen, meint dabei Nachkommastellen.

vop2_sum = 54321
nop2_sum = 0.67800003
Ergebnis auf 7 Dezimalstellen: 54321.68
op2_sum = 54321.68

Für die Muliplikation gilt das ebenfalls. Beide Ergebnisse stimmen auf 7 
Stellen überein.

Wo ist also das Problem? Works as designed. ANSI-konform ist das nicht, 
weil da für double 10 Stellen verlangt werden, aber so ist avr-gcc nun 
einmal gebaut.

Wer nicht glaubt, dass sizeof(double)==4, der sehe sich mal die Adressen 
von vop2ZT und vop2_sum an.

Autor: Nino K. (lnino)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ A. K. : Das heisst der avr-gcc kann das einfach nicht besser?

Vielen Dank.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau das heisst es. Ganzzahlig kann er jedoch 64 Bits.

Autor: Nino K. (lnino)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ A. K. : Vielen Dank für deine Hilfe. Dann ich meine Fehlersuche nun 
stoppen. :-)

Autor: Maxx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Für die Muliplikation gilt das ebenfalls. Beide Ergebnisse stimmen auf 7
> Stellen überein.
>
> Wo ist also das Problem? Works as designed.

Noe. nicht wie designed. Designed sind 52 signifikante Bits im double. 
Das wären 15,6 signifikante Dezimalstellen.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Maxx schrieb:

> Noe. nicht wie designed. Designed sind 52 signifikante Bits im double.
> Das wären 15,6 signifikante Dezimalstellen.

Der Designer von avr-gcc sah das offenbar anders. Dass avr-gcc nicht 
C89-konform ist schrieb ich oben schon, wobei C89 übrigens keine 52 
Mantissenbits verlangt.

Autor: Maxx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist ja auch kein Angriff auf dich gewesen, sondern, dass es nicht dem 
Design entspricht.

Die single/double Formate standardisiert das IEEE 754.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Maxx schrieb:

> Die single/double Formate standardisiert das IEEE 754.

Das hat aber erst seit C99 einen Bezug zu C. Davor nicht. Man kann also 
nicht darauf vertrauen, dass "double" dem IEEE Format entspricht. Bei 
8-Bit Controllern erst recht nicht.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Maxx schrieb:
> Ist ja auch kein Angriff auf dich gewesen, sondern, dass es nicht dem
> Design entspricht.

Welchem "Design"? Bei avr-gcc wurde double mit Absicht nur 32 Bit breit 
gemacht, also entspricht das dessen Design. Es entspricht vielleicht 
nicht der C-Spezifikation, aber das ist ja schon bekannt.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> ANSI-konform ist das nicht,
> weil da für double 10 Stellen verlangt werden

Ich glaube, es wäre sogar ANSI-konform gewesen ;-), es war sogar noch
konform zu den ersten Drafts von ISO-C99, die Forderung mit
mindestens 10 Stellen Genauigkeit (die bspw. durchaus auch von einem
48-bit-Format erfüllbar wäre, 64 bit sind nirgends vorgeschrieben)
kam erst kurz vor dem endgültigen Standard rein.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich das richtig sortiere, dann sind die 10 Stellen bereits 
Bestandteil von ANSI/C89, während C99 effektiv IEEE754 vorschreibt.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
C99 schreibt:

FLT_DIG   6
DBL_DIG  10
LDBL_DIG 10

als minimale Werte vor.

OK, vielleicht habe ich mich auch geirrt, dass es in einem der Drafts
nicht so gewesen wäre, ich finde zumindest in den alten, die ich noch
habe, nichts mehr.  Ist ja auch irrelevant, da der Standard es so
vorschreibt wie oben gezeigt.  Das macht AVR-GCC derzeit nicht, eine
64-bit-FP-Implementierung zu haben, ist zwar ein frequently requested
item, es gab auch schon mal jemanden, der Interesse geäußert hat (und
möglicherweise den notwendigen Durchblick in die GCC-Details), das zu
machen, aber seither habe ich von ihm auch nur nichts mehr gehört. :(

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wirst recht haben. Ich stolperte letzthin zwar über einen Zusammenhang 
zwischen C99 und einem IEC Floating-Point Standard, der um's Eck rum auf 
den IEEE754er rauslief, aber das ist evtl. nicht zwingend. Da unsereiner 
von solchen Standards grundsätzlich immer nur Drafts zu sehen kriegt, 
bleibt das eben alles indirekt oder inoffiziell.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Da unsereiner
> von solchen Standards grundsätzlich immer nur Drafts zu sehen kriegt,
> bleibt das eben alles indirekt oder inoffiziell.

Vom C-Standard gibt's ja zum Glück eine "semi-offizielle" Version:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1336.pdf

Die ist zwar als "Draft" (und zwar schon für C1x) markiert, ist aber
in Wirklichkeit der Text des offiziellen Standards mit den eingear-
beiteten drei technical corrigenda.  Für die (etwas bekanntere)
Vorgängerversion:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf

steht das noch etwas offensichtlicher drüber (Standard + TC1/TC2).

Die Mindestwerte deuten meines Erachtens darauf hin, dass man eine
48-bit-Implementierung (8 Bit Exponent, denn nur 1E-37...1E37 ist
gefordert und 40 Bit Mantisse) auf jeden Fall damit abgedeckt
sehen möchte, nur eben eine 32-bit-Implementierung nicht mehr.

Leider dürfte es für den GCC ungleich schwieriger sein, ihm eine
48-bit-Implementierung (für den AVR-GCC) beizubringen denn eine mit
64 bit, da er intern auf einen derartigen Datentypen m. W. nicht
vorbereitet ist.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.