Forum: Mikrocontroller und Digitale Elektronik float in int umrechnen


von Dag (Gast)


Lesenswert?

Hallo,
ich hab eine Formel, welche eigentlich eine Rechnung in float vornimmt.
Soll es aber nicht, sondern in int.
z.B.
y=(x-261.12)/7.23
wobei x verschiedene werte annimmt(auch kleiner 261)

Wie muß ich jetzt die Formel umschreiben, damit er nicht mit
Kommawerten rechnet? Problem dabei ist die Bereichsbegrenzung vom
integer.

Für Vorschläge wäre ich dankbar.

von Joerg Wunsch (Gast)


Lesenswert?

Du skalierst sie.

Du schreibst nicht, für welchen Prozessor/Compiler, ich gehe mal davon
aus, daß Du einen signed int von 16 Bits hast, der kann also Werte von
-32768 bis 32767 abbilden.  Nun brauchst Du die minimalen und
maximalen Werte, die x annehmen kann, damit bekommst Du den
größtmöglichen Skalierungsfaktor.  Mal angenommen, x kann maximal 300
sein, dann wäre der Faktor 32767 / 300 =~ 100.  (Schade, 128 wäre
einfacher, weil man dann nur 7 bits nach links schieben muß.)

Es dürfte genauer werden, wenn Du ausklammerst und den konstanten
Quotienten auf der rechten Seite vorab skalierst.

von Dag (Gast)


Lesenswert?

Danke,
hab es aber ehrlich gesagt nicht ganz verstanden.
Ich arbeite mit dem AT90S4433.
Also mir stehen 16 Bit Register zur Verfügung.
Die x-Werte kommen aus dem internem AD Wandler und können
Werte von 0 bis 1024 annehmen.
Der y-Wert soll ein integer sein.

Danke

von Rolf F. (Gast)


Lesenswert?

Ich würde so skalieren:


#include <limits.h>

y = (int) ( (x-261.12)/7.23  SKAL  ((float) INT_MAX) );


SKAL muss so gewählt werden, dass der Wert von (x-261.12)/7.23 * SKAL
betragsmäßig maximal 1,0 ist.

von Dag (Gast)


Lesenswert?

Tut mir leid,
aber das funktioniert nicht.
Habe SKAL einen Wert von 1/110 zugeordnet.
Wofür ist den eigentlich die limits.h da?
Was soll den in dieser Gleichung passieren?

Danke

von Dag (Gast)


Lesenswert?

Schuldigung,
geht doch, hatte den falschen SKAL-Faktor.
Da von 0 bis 1024 -> SKAL=32767*1024=32
y=(int) ((x-261.12)/7.23*32)*((float) INT_MAX) );

So geht es jetzt bei mir.
Würde mich trotzdem freuen, wenn mir einer erklärt, was nun genau
in der Gleichung passiert.
Mich interessiert besonders das (int) und (float)

von Rolf F. (Gast)


Lesenswert?

Also (int) wandelt (engl. castet) in den Datentyp int um usw..

Und SKAL muss der Kehrwert des betragsmäßigen Maximalwerts (von
(x-261.12)/7.23 ) sein; dann liegt y im Bereich -INT_MAX ... INT_MAX,
wobei -INT_MAX oder -INT_MAX-1 gleich INT_MIN sein sollte (genau stehts
in limits.h).
Durch diese Skalierung ist der Rundungsfehler minimal.
Wenn man es genau machen will, dann berücksichtigt man, dass beim cast
abgeschnitten (abgerundet) wird und rundet entspechend richtig:


#include <limits.h>

f_tmp = ( (x-261.12)/7.23  SKAL  ((float) INT_MAX) );

f_tmp += (dtmp > -0.5) ? 0.5 : -0.5;

y = (int) f_tmp;

von Rolf F. (Gast)


Lesenswert?

Nachtrag: Vor der letzten Zeile sollte wegen eventuellen Rundungsfehlern
noch

if (f_tmp > ((float) INT_MAX)
  f_tmp = INT_MAX;
if (f_tmp < ((float) -INT_MAX)
  f_tmp = -INT_MAX;


eingesetzt werden.

von Dag (Gast)


Lesenswert?

Vielen Dank an Rolf.
Habe es jetzt so einigermaßen verstanden und es funktioniert super.

Danke

von Rolf F. (Gast)


Lesenswert?

Gut.
Übrigens muss man im Allgemeinen noch auf NAN und manchmal auch auf
+inf und -inf überprüfen. isnan() und isinf() sind deshalb auch beim
mspgcc dabei (notfalls kann man das bischen Code nach IEEE 754 auch
selbst schreiben).

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.