Forum: Mikrocontroller und Digitale Elektronik 8051: ungenaue Fließkomma-Berechnung?


von Peter D. (peter_d)


Lesenswert?

Hallo miteinander,

ich habe ein etwas mystisches Problem mit Fließkomma-Berechnungen.

Bevor nun jemand die Glaskugel hervorkramen muss: ;-)

- Prozessor: ADuC834
- Compiler:  KEIL: C51.exe X3.35 vom 21.12.1992
- Linker:    KEIL: L51.exe V2.8  vom  2. 1.1991
- Libraries: KEIL: C51S.lib und C51FPS.lib vom 23. 9.1991
- Pragmas:   code symbols small regparms

Die Firmware macht folgendes:

- eine Temperatur (float!) messen und in bestimmten Abständen (ca. 10 
Sek.) im Flash speichern (float!)
- nach jeder Temperatur-Messung folgende Berechnung ausführen:

    y += P1 hoch (AT - P2)

'y' ist eine globale Variable und wird bei Start der Messung auf 0 
gesetzt. P1 und P2 sind zwei globale Parameter (float!), die während der 
Messung konstant sind. AT ist die aktuell gemessene Temperatur (float!). 
P1 liegt so bei 1.2F und P2 bei 50.F

der Source-Code dazu ist:
1
y += pow(P1, (AT - P2));

am Ende der Messung wird 'y' gespeichert und zur PC-Software übertragen.

Auf dem PC läuft eine ebenfalls von mir geschriebene Windows-Software 
(geschrieben mit Microsoft Visual Studio 2008, C++),
die nun alle gespeicherten Temperaturwerte aus dem Flash des ADuC834 
ausliest (über RS232) und auf Harddisk speichert.

Lasse ich nun die PC-Software 'y' berechnen (alles in float!):
1
y = 0;
2
for(i=0; i<maxwerte; i++) {
3
   y += pow(P1, (T[i] - P2)); // T[i] ist die Temperaturmessreihe!
4
}

so kommt bei einer Messreihe mal der gleiche Wert wie im ADuC835, bei 
einer anderen Messreihe aber auch ein stark abweichender (ca. 30% 
höherer) Wert heraus.

In Excel transferierte Messreihen ergeben dort immer den gleichen Wert 
für 'y' wie in meiner Windows-Software, so dass ich den Rechenfehler im 
ADuC834 vermute.

Hat jemand schon Erfahrung mit der Rechengenauigkeit der 
Keil-Floating-Point-Emulation?

Könnte es sein, dass bei sehr kleinen Exponenten 
(Temperatur-Differenzen) oder negativen Exponenten die Keil-Library 
schwächelt?

Viele Grüße
Peter

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du zeigst keinen Sourcecode, sondern nur komplett nichtssagende 
Schnipsel.

Davon abgesehen wird die Genauigkeit der FP-Routinen für Deinen 8051 
nicht der des PCs entsprechen; höchstwahrscheinlich ist ein float 32 
Bit groß (statt 64 wie auf dem PC).

von Maxxie (Gast)


Lesenswert?

Oder noch kleinere float-Typen.

Das aber ist nicht das Problem, denn auch mit geringen Genauigkeiten 
kann man noch rechnen, wenn man sich ein paar Gedanken über die 
Reihenfolge der Operationen macht.

Generell: Additionen/Substraktionen nach Multiplikation/Division wenn 
sich der Term umstellen lässt. (siehe Auslöschungen und co 
http://de.wikipedia.org/wiki/Gleitkommazahl#Ausl.C3.B6schung )

Also statt
1
y += pow(P1, (AT - P2));
lieber
1
y += pow(P1, AT) / pow(P1, P2));

Erhöht den Rechenaufwand, reduziert den Fehler.

von Matthias K. (matthiask)


Lesenswert?

> Compiler:  KEIL: C51.exe X3.35 vom 21.12.1992
Recht alte Version, aber eigentlich noch gut einsetzbar.

Versuch doch mal die betreffenden Funktionen mit einen anderen Compiler 
zu testen. zB. SDCC oder uc51, welche auch Float in der Demoversion 
unterstützen.

Float ist bei Keil (V3) 4 Byte groß, (+-1,176E-38 bis +- 3,40E+38)
IEEE-54 Standard

Im Handbuch zu Version 3 steht einiges zu den Besonderheiten von 
float-Berechnungen, ua. auch, wie Fehler bei Berechnungen abgefangen 
werden können.

von Tropenhitze (Gast)


Lesenswert?

>X3.35

Ich habe mal V3.20 und V3.40 aufgerufen. Beide melden ein Vn.nn Ist 
Deine Version tatsächliche eine Xn.nn?
Vielleicht ist die in ihren Möglichkeiten 'abgemagert'.

von Matthias K. (matthiask)


Lesenswert?

>X3.35

Stimmt, X habe ich auch noch nicht gesehen.

Nutzt Du manchmal Float-Berechnungen im Interrupt und Hauptprogramm? 
Wenn ja, musst Du bei Keil in der Interruptfunktion vorher den 
Float-Status sichern und wiederherstellen.

von Peter D. (peter_d)


Lesenswert?

Hallo an alle,

vielen Dank für die schnellen Antworten.


Maxxie schrieb:
> Also statt y += pow(P1, (AT - P2));lieber y += pow(P1, AT) / pow(P1, P2));
> Erhöht den Rechenaufwand, reduziert den Fehler.

dass ist doch schon mal ein brauchbarer Hinweis. Trotz 30 Jahren 
Programmiererfahrung ist mir dieser Umstand neu. Aber gut man, lernt ja 
nie aus ;-)

Dass mit dem X hätte ich lieber nicht schreiben sollen ;-) Denkt Euch 
einfach anstelle des X ein V.


Mathias K. schrieb:
> Nutzt Du manchmal Float-Berechnungen im Interrupt und Hauptprogramm?

Nein, es wird nur im Main gerechnet.


Rufus t. Firefly schrieb:
> Davon abgesehen wird die Genauigkeit der FP-Routinen für Deinen 8051
> nicht der des PCs entsprechen; höchstwahrscheinlich ist ein float 32
> Bit groß (statt 64 wie auf dem PC).

Meines Wissen entspricht der 'float' beim MS Compiler dem IEEE-Standard 
(also 32-Bit). Ich habe zum Vergleich im meinem Windows-Programm die 
Berechnung mit 'float' und einmal mit 'double' durchlaufen lassen und 
eine Abweichung war nur in der 6. Nachkommastelle zu erkennen.

Von daher denke ich nicht, dass es die Genauigkeit (32- oder 64-Bit) 
ist, sondern die verwendeten Berechnungs-Algorithmen. Auf dem PC hat man 
einen ziemlich guten Co-Prozessor, der ja heutzutage im Vergleich zum Co 
beim Intel-386er richtig rechnen sollte ;-)

Grüße
Peter

von Иван S. (ivan)


Lesenswert?

Peter D. schrieb:

> Auf dem PC hat man einen ziemlich guten Co-Prozessor,

Wo? Heutzutage ist die FPU im Prozessor integriert?

> der ja heutzutage im Vergleich zum Co beim Intel-386er richtig rechnen sollte 
;-)

Was hast Du am 80x87 auszusetzen?

Iwan

von Peter D. (peter_d)


Lesenswert?

Hallo Ivan,

gehen deine Fragen nicht etwas am Thema vorbei?

Ivan schrieb:
> Wo? Heutzutage ist die FPU im Prozessor integriert?

Das ist doch nun Korinthen-Kackerei, ob der mathematische Prozessor 
intern oder extern sitzt. Es ging doch nur darum, dass heutzutage im PC 
schon lange nicht mehr mit Fließkomma-Emulatoren gerechnet wird.

Ivan schrieb:
> Was hast Du am 80x87 auszusetzen?

Nichts, aber es gab mal ein Gerücht, dass der 80387 nicht "richtig" 
rechnen würde. Zwar nur unter ganz speziellen und schwer herzustellenden 
Bedingungen. Viel habe ich dazu im Web nicht gefunden, aber z.B.:

http://www.heise.de/ct/artikel/Prozessorgefluester-285634.html

Aber, wie schon gesagt, dieser Beitrag ist OffTopic!

Grüße
Peter

von Tobi (Gast)


Lesenswert?

kein Gerücht sondern FDIV Bug.

von Maxxie (Gast)


Lesenswert?

Der war aber bereits bei der integrierten Pentium FPU. P60 und P66, 
nicht in den 80x87-Chips, welche externe FPUs waren.

Die errate waren damals noch lang nicht so öffentlich bei Intel und co, 
wie sie heute sind. Der FDIV -Bug war da einer der Weckrufe für deren 
breite Offenlegung. Man muss bei einigen Prozessor-Bugs früher oft immer 
noch bei "Gerücht" bleiben.

Es gab doch sogar noch Wettbewerbe darum, wer als erster "verheimlichte" 
Opcodes findet und richtig interpretiert. (wie z.B. LOADALL)

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.