Forum: Mikrocontroller und Digitale Elektronik Hilfestellung Konvertierung byte array to 32-Bit Floating-Point (single precision)


von Mo (Gast)


Lesenswert?

Hi ich habe folgendes Problem.

Ich erhalte 4 bytes die in einem byte Array gespeichert sind.
Diese 4 bytes sollen in einen 32-Bit Floating-Point (single precision) 
konvertiert werden.
1
byte[] ByteArray; 
2
3
ByteArray[0] = 0x56;
4
ByteArray[1] = 0x09;
5
ByteArray[2] = 0x00;
6
ByteArray[3] = 0x00;
7
8
float value = BitConverter.ToSingle(this.ByteArray, 0);

Der Wert sollte hier 2390 sein. Ich erhalte allerdings in C# den Wert: 
3.349103E-42

von Oliver S. (oliverso)


Lesenswert?

Das wird wohl ein little-/big-Endian-Problem sein.

Oliver

von Mo (Gast)


Lesenswert?

Hab auch die bytes mal verdreht. Der Wert erscheint trotzdem falsch.

von Oliver S. (oliverso)


Lesenswert?

Ja, dann ist die Funktion kaputt oder die Doku dazu falsch. Es kann aber 
auch, und das ist sehr viel wahrscheinlicher, ein Fehler in Zeile 42 von 
deinem Programm sein.

Oliver

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Mo schrieb:
> Ich erhalte 4 bytes die in einem byte Array gespeichert sind.
> Diese 4 bytes sollen in einen 32-Bit Floating-Point (single precision)
> konvertiert werden.
Ein Dejavu...
Vielleicht hilft der Beitrag "Convert char array to float value"

Oliver S. schrieb:
> Das wird wohl ein little-/big-Endian-Problem sein.
Oder die aufgerufene Funktion funktioniert nicht wie geplant.

von Oliver R. (superberti)


Lesenswert?

In Deinem Array steht kein Float, das ist ein Int32!

Gruß,
Oliver

von Mo (Gast)


Lesenswert?

Ja so wie es nun aussieht wird in meiner C# Oberfläche der Wert flasch 
dragestellt. Wenn ich den Wert 2390 in ein byte array konvertiere 
erhalte ich
0x56 0x09 0x00 0x00 zurück.

von Oliver S. (oliverso)


Lesenswert?

Lothar M. schrieb:
> Oder die aufgerufene Funktion funktioniert nicht wie geplant.

Das tut die schon, die liefert ja das richtige Ergebnis für das, was sie 
tun soll.

0x56090000 soll 2390 ergeben.

Etwas scharfes Hinsehen, und man erkennt…

Oliver

von PittyJ (Gast)


Lesenswert?

Genau, das ist ein int.
Hex 0x956 = Dezimal 2390

von Mo (Gast)


Lesenswert?

Der Wert wird schon float umgewandelt. Im Debug-Fenster steht folgendes:
Name: value
Wert: 3.349103E-42
Type: float

von PittyJ (Gast)


Lesenswert?

Vielleicht noch einmal die Details zu Floats anschauen:

https://de.wikipedia.org/wiki/IEEE_754

von FOp (Gast)


Lesenswert?

Mein C# meint
0,96,21,69 = 0x00, 0x60, 0x15, 0x45
wären die Bytes für 2390. Keine Ahnung, wie da der Zusammenhang zu 
Deinen Bytes ist.

von Axel R. (axlr)


Lesenswert?

Oliver S. schrieb:
> und man erkennt…
09 56 sind 2390
dass "varkehrtrum" is ;)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Mo schrieb:
> ByteArray[0] = 0x56;
> ByteArray[1] = 0x09;
> ByteArray[2] = 0x00;
> ByteArray[3] = 0x00;
> Der Wert sollte hier 2390 sein.
Das stimmt nicht ganz...

https://gregstoll.com/~gregstoll/floattohex/

EDIT: oha, da dümpeln wir ja grade noch bei den absoluten Grundlag zum 
Thema "Darstellung binärer Zahlen" herum.

: Bearbeitet durch Moderator
von c-hater (Gast)


Lesenswert?

Mo schrieb:

> Der Wert sollte hier 2390 sein.

Wie, zum Teufel, kommst du auf diese Schnapsidee?

In dem Float-Format, welches .net benutzt, würde 2390 die Bytefolge 
0x00, 0x60, 0x15, 0x45 ergeben.

Und das Format, was .net da benutzt, ist ein ziemlich standardmäßiges. 
IEEE- irgendwas (genaue Zahl vergessen).

Das Problem liegt also wohl in der Quelle, die benutzt offensichtlich 
ein anderes Float-Format. Wenn die Bytes, die du geliefert hast, 
überhaupt eine Float-Zahl darstellen. 2390 jedenfalls stellen sie 
zumindest in KEINEM der mir bekannten 32Bit-Float-Formate dar. Was 
natürlich sicher nicht ausschließt, dass es eins geben mag, was ich 
nicht kenne.

Genau das ist ja das Schöne an Standards: es gibt so viele davon...

von Maxim B. (max182)


Lesenswert?

Kann man vielleicht so machen?
1
union itof{
2
    u8 ByteArray[4];
3
    u32 intconv32;
4
        } ifconv;
5
float fa;
6
7
   ifconv.ByteArray[0] = 0x56;
8
   ifconv.ByteArray[1] = 0x09;
9
   ifconv.ByteArray[2] = 0x00;
10
   ifconv.ByteArray[3] = 0x00;
11
12
   fa = (float)intconv32;

von Oliver S. (oliverso)


Lesenswert?

c-hater schrieb:
> 2390 jedenfalls stellen sie
> zumindest in KEINEM der mir bekannten 32Bit-Float-Formate dar. Was
> natürlich sicher nicht ausschließt, dass es eins geben mag, was ich
> nicht kenne.

Jetzt schwächelst du aber gewaltig. Jemandem wie dir muß die Lösung 
direkt ins Auge springen, alles andere wäre deinem Ruf abträglich.

Welches geheime Format das ist, steht ja schon weiter oben, aber für 
dich nochmal: 32 Bit (u)int

Oliver

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

P.S. Schreibfehler.
Letzte Befehl natürlich
1
fa = (float)ifconv.intconv32;

von Mo (Gast)


Lesenswert?

Ok vielen vielen Dank für eure Hilfe

von uwe (Gast)


Lesenswert?

0x0000_0956 = 2390 ... welch ein Zufall ;-)

Beitrag #6917460 wurde vom Autor gelöscht.
von Maxim B. (max182)


Lesenswert?

Wenn es um Konstanten geht, kann man sicher auch ohne Array
1
u32 ByteArray; 
2
float fa;
3
4
#define Zahl0 0x56
5
#define Zahl1 0x09
6
#define Zahl2 0
7
#define Zahl3 0
8
9
ByteArray = (u32) Zahl0;
10
ByteArray |= ((u32)Zahl1 << 8);
11
ByteArray |= ((u32)Zahl2 << 16);
12
ByteArray |= ((u32)Zahl3 << 24);
13
14
fa = (float)ByteArray;
Wenn keine Konstanten, dann wird Code zu groß.

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Oliver S. schrieb:

> Jetzt schwächelst du aber gewaltig.

Nicht wirklich...

> Welches geheime Format das ist, steht ja schon weiter oben, aber für
> dich nochmal: 32 Bit (u)int

Und du glaubst ernsthaft, dass ich das nicht erkannt hätte? Dann lies' 
das Posting nochmal und taste es auf Hinweise von Sarkasmus ab...

von Wolfgang (Gast)


Lesenswert?

Mo schrieb:
> Der Wert sollte hier 2390 sein. Ich erhalte allerdings in C# den Wert:
> 3.349103E-42

Wie kommst du auf die Idee, dass deine vier Byte ein single Precision 
Float repräsentieren sollen.

von W.S. (Gast)


Lesenswert?

c-hater schrieb:
> Wie, zum Teufel, kommst du auf diese Schnapsidee?

Tja, manche Leute sind öfter als andere geneigt, 4 nebeneinander 
geschriebene Bytes als eine Gleitkommazahl zu verstehen. Das stimmt hier 
aber nicht, denn es sind die 4 Bytes aus einem long oder unsigned long.

Wenn man das also (zu Fuß) ins Gleitkommaformat konvertieren will, dann 
geht das mal ganz grob skizziert etwa so:
1. Zusammenfassen der 4 Bytes zu einer long Variablen.
   (wenn negativ, dann neg.VZ merken und -Zahl machen, d.h. positiv 
machen)
2. diese long Variable solange nach links verschieben, bis das Bit 1<<23 
= 1 ist. Das ergibt die Mantisse.
 (Ausnahme: null, ist vorher abzuprüfen)
 Bei alldem die Anzahl der Verschiebungen testen.
3. zu einem Offset (zumeist 80h) die Zahl der Verschiebungen addieren. 
Das ergibt den Exponenten
4. die Exponent und Mantisse einsortieren:
   Byte[0] = Exponent
   Byte[1] = Bits 23..16 der Mantisse
   Byte[2] = Bits 15..8 der Mantisse
   Byte[3] = Bits 7..0 der Mantisse
5. Exponent um 1 Bit nach rechts verschieben.
   Das Bit 0 kommt dann ins Bit 7 von Byte[1]
   und das Vorzeichenbit kommt in Bit 7 von Byte[0]

So, in C macht das ne Bibliotheksfunktion, da braucht man lediglich ne 
Zuweisung zu schreiben und den Rest macht der Compiler. Aber der TO hat 
ja wissen wollen, wie es geht. Und zwar ohne irgend einen ominösen 
Bitconverter.

W.S.

von c-hater (Gast)


Lesenswert?

W.S. schrieb:

> Zuweisung zu schreiben und den Rest macht der Compiler. Aber der TO hat
> ja wissen wollen, wie es geht. Und zwar ohne irgend einen ominösen
> Bitconverter.

Der ist nicht "ominös", sondern sogar extrem gut dokumentiert. Was ihn 
allerdings natürlich keinesfalls dagegen schützt, von Vollidioten falsch 
benutzt zu werden...

Ist dann wie bei jeder anderen Software auch: Shit in->shit out.

von Wolfgang (Gast)


Lesenswert?

c-hater schrieb:
> Das Problem liegt also wohl in der Quelle, die benutzt offensichtlich
> ein anderes Float-Format. Wenn die Bytes, die du geliefert hast,
> überhaupt eine Float-Zahl darstellen.

Mir ist kein Float-Format bekannt, dass die selben Bytes wie int32 
ergibt.

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.