Forum: Mikrocontroller und Digitale Elektronik Float zerlegen Vorkomma Nachkomma


von Thomas (Gast)


Lesenswert?

Hallo zusammen,

ich habe ein Problem, eine Float-Variable in zwei Integer-Variablen zu 
zerlgen. Ich möchte die Vorkomma- und die Nachkommastelle getrennt 
speichern bzw.  in einem unsigned int. Vorkomma im Highbyte, Nachkomma 
im Lowbyte oder umgekehrt, egal.

Ich habe nun folgendes probiert:
1
var_float= 95.71;
2
uint16_t daten_in;
3
daten_in = (int)(var_float);  // Vorkomma
4
daten_in= daten_in << 8;
5
daten_in= (var_float - (daten_in >> 8))*10;

Wenn ich das dann wie folgt ausgeben möchte:
1
vorkomma = daten_in >> 8;
2
nachkomma= daten_in;

Bei der Ausgabe stimmt dann die Nachkommastelle, aber die Vorkommastelle 
ist immer null.

Grundsätzlich scheint es ja zu funktionieren, nur mit der Bit Hin- und 
herschieberei scheint was nict zu stimmen.

Wäre Klasse, wenn mich da jemand auf den richtigen Weg bringen könnte.

Beste Grüße
Thomas

von Bernhard S. (b_spitzer)


Lesenswert?

var_float= 95.71;
uint16_t daten_in;
daten_in = (int)(var_float);  // daten_in ist jetzt 95
daten_in= daten_in << 8;      // daten_in ist jetzt 24320
daten_in= (var_float - (daten_in >> 8))*10;
          // (95.71 - 95) * 10 => daten_in ist jetzt 7


vorkomma = daten_in >> 8;     // 7/256 = 0
nachkomma= daten_in;          // nachkomma ist 7


Sehr viel Aufwand für Datenvernichtung... wie wäre es zum Test mit ein 
paar Zwischenvariablen mehr?? Außerdem ist die Anzahl der 
Nachkommastellen variabel und float kann auch ein Vorzeichen haben.
Übrigens ist 95,71 nicht exakt als Float darstellbar (sollte 95,7099 
ergeben).

von Bernhard S. (b_spitzer)


Lesenswert?

Wie wäre es damit... 3 Nachkommastellen sollen es hier sein.

var_float= 95.71;
int32_t tausendstel;
uint16_t vorkomma, nachkomma;

bit vorzeichen=0;           // Datentyp kontrollieren! 1: negativ

tausendstel = (long) (var_float * 1000);   // Wertebereich 
kontrollieren!
if (tausendstel < 0)
{   tausendstel = -tausendstel;  // negative Zahl
    vorzeichen = 1;
}
vorkomma = (unsigned int)(tausendstel/1000); // Wertebereich 
kontrollieren!
nachkomma = (unsigned int)(tausendstel%1000);

von Dr. Sommer (Gast)


Lesenswert?

Du musst nachschauen in welchem Format die floats bei dir gespeichert 
sind, dann den Exponenten auslesen, dadurch ergibt sich welche Bits der 
Mantisse vor und welche nach dem Komma stehen. (es muss nicht 
notwendigerweise beide geben!). Dementsprechend kannst du dann die Bits 
der Mantisse shiften und woanders hin kopieren, um die getrennt zu 
haben. Interessant wäre jetzt zu wissen, ob das mit der 
C-Standard-Library irgendwie portabel geht. Das ganze wäre sogar recht 
effizient (wenn die CPU einen Barrel-Shifter hat, in O(1), ansonsten in 
O(exponent), sozusagen).
Dieser wilde Algorithmus mit Division etc. von Bernhard ist jedenfalls 
langsamer...

von (prx) A. K. (prx)


Lesenswert?

Geht es hier um "schnell" oder um "gut"?

von Dr. Sommer (Gast)


Lesenswert?

Thomas schrieb:
> Vorkomma im Highbyte, Nachkomma
> im Lowbyte oder umgekehrt, egal.

Ein Byte wird wohl nicht reichen, was, wenn die Zahl 10101000000000000 
oder so ist...

von (prx) A. K. (prx)


Lesenswert?

Schau dir mal die Standardfunktion modf() an, bzw. deren float-Variante 
modff(). Taugt evtl. als Basis.

von Jürgen S. (jurs)


Lesenswert?

Thomas schrieb:
> ich habe ein Problem, eine Float-Variable in zwei Integer-Variablen zu
> zerlgen. Ich möchte die Vorkomma- und die Nachkommastelle getrennt
> speichern bzw.  in einem unsigned int. Vorkomma im Highbyte, Nachkomma
> im Lowbyte oder umgekehrt, egal.

Mit Rundung auf eine Nachkommastelle beispielsweise:

float var_float= 95.771;
unsigned int hilo_float;
hilo_float=(round(var_float*10)/10)*256 + round(var_float*10)%10;

Für Rundung auf zwei Nachkommastellen 10 durch 100 ersetzen.

von Mathe (Gast)


Lesenswert?

95.71 = 0.9571*10^2
Fliesskomma wird in Mantisse und Exponent gespeichert.
Ist also schon aufgeteilt.
Eine Aufteilung in 2 Integer Werten verringert die Genauigkeit
oder erhöht den Speicherplatzbedarf, meisst aber beides.

von amateur (Gast)


Lesenswert?

Definiere doch Deine uint16 als union zweier Bytes.
und versuche es mit:
xxx.high = (int)yyy;
xxx.low  = (int)((yyy - (int)yyy) * 100.0);
oder so...

von W.S. (Gast)


Lesenswert?

Thomas schrieb:
> ich habe ein Problem

Ja. Das sehe ich. Dein Problem ist, daß du offenbar garnicht weißt, was 
du da eigentlich haben willst. Wie bittesehr soll eine Nachkommastelle 
in einem Byte aussehen? Und was ist für dich eine Nachkommastelle? 
Floats sind im Binärformat und nicht dezimal.

Ich geb dir mal nen Tip:

unsigned char vk, nk;
unsigned int W;
float F;

W = floor(F*256);
vk = W>>8;
nk = W&255;

so. Das wär's. Allerdings mußt du dich an den Gedanken gewöhnen, daß die 
Bits in nk realiter eine andere Bedeutung haben als du glaubst:
das MSB in nk hat den Wert 0.5, das nächstkleinere 0.25, dann 0.125 usw.

W.S.

von daniel root (Gast)


Lesenswert?

Thomas schrieb:
> daten_in= (var_float - (daten_in >> 8))*10;

daten_in |= (var_float - (daten_in >> 8))*10;

und pass auf die Wertebereiche auf

von Jörg (Gast)


Lesenswert?

Hallo,

ich habe ein ähnliches Problem oder vielleicht das gleiche. Vielleicht 
kann ich es noch ausführlicher beschreiben.

ICh habe ebenfalls eine float Variable, dessen Vorkomma-Dezimal-Wert 
nicht über 250 hinaus geht. Als Nachkomma brauche ich nur zwei Stellen 
maximal.

ICh würde halt nun gerne Vor- und Nachkomma voneinander trennen und 
entweder in zwei Variablen oder ebennur in einer speichern.

Ich greife das Beispiel von oben einmal auf:
1
var_float= 95.71;
Nun sollen sein:
1
vorkamma = 95 (dezimal)
2
nachkomma =71  (dezimal)
3
4
vorkamma = 01011111
5
nachkomma = 01000111

Ich hoffe, dass das verständlich ist.

Das Ganze könnte man ja nun auch in eine Variable packen:
1
zusammen= 01011111 01000111

Dann hätte man in einer Variable als Highbyte die Vorkommastelle und als 
Lowbyte die Nachkommastelle. Aber vorsicht beim Auslesen. Lowbyte lesen 
und dann das Highbyte an die Lowbyte-Stelle schieben, damit es vom 
Dezimalwert her passt.

Sinn des Ganzen ist, dass die Daten auf mehrere Art und Weisen 
ausgegeben und weiterverarbeitet werden und es deswegen schön wäre, sie 
in diesem Format vorliegen zu haben.

Ich werde mir die Lösungen und Hinweise von oben mal anschauen und mal 
sehen, was ich selbst für mein Problem daraus machen kann.

Allerbeste Grüße
Jörg

von (prx) A. K. (prx)


Lesenswert?

Schon mal an Festkommarechnung gedacht?

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.