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


von Nino K. (lnino)


Angehängte Dateien:

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
von (prx) A. K. (prx)


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.

von Maxx (Gast)


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

von Nino K. (lnino)


Lesenswert?

Vielen Dank für die Antworten.

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

von Floh (Gast)


Lesenswert?

Zeig doch einfach dein Programm als Dateianhang.

von Maxx (Gast)


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.

von (prx) A. K. (prx)


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.

von Nino K. (lnino)


Lesenswert?

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

Vielen Dank.

von (prx) A. K. (prx)


Lesenswert?

Genau das heisst es. Ganzzahlig kann er jedoch 64 Bits.

von Nino K. (lnino)


Lesenswert?

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

von Maxx (Gast)


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.

von (prx) A. K. (prx)


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.

von Maxx (Gast)


Lesenswert?

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

Die single/double Formate standardisiert das IEEE 754.

von (prx) A. K. (prx)


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.

von Rolf Magnus (Gast)


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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von (prx) A. K. (prx)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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

von (prx) A. K. (prx)


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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

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.