4 Byte in 1 float wandeln

Gast #3195176
Lesenswert?
• ▲
▼
Hallo,

ich grübel schon ewig an folgendem Problem:

ich habe in data[0], data[1], data[2] und data[3]
jeweils ein Byte einer übertragenen float Zahl.

Diese zerstückelte float Zahl möchte ich nun wieder zusammen setzen.

Dazu habe ich mir folgendes gedacht:

int i,j,k,l;
float d;

i = data[0];
j = data[1];
k = data[2];
l = data[3];

d = (l<<24) | (k<<16) | (j<<8) | i;

printf("Value: %f",d);


Leider funktioniert es nicht, bzw es wird eine falsche float Zahl 
angezeigt.
Gast #3195200
Lesenswert?
• ▲
▼
Hi

hört sich nach einem Bigendian/Littleendian Problem an.
Vorrausgesetzt, beides sind IEEE floats (was mit einiger Sicherheit
anzunehmen ist, probier einfach mal

int i,j,k,l;
float d;

i = data[3];   // umgekehrte Reihenfolge wie oben!!!
j = data[2];
k = data[1];
l = data[0];

d = (l<<24) | (k<<16) | (j<<8) | i;

printf("Value: %f",d);

Reiner
Gast #3195551
Lesenswert?
• ▲
▼
> Ein float kommt da schon raus. Nur halt nicht der, der vorher
> reingesteckt wurde. ;-)

mit kreativem Casten (und einem passendem Speicheralignment) geht das 
schon auch so:
1
$ cat main.c
2
#include <stdio.h>
3
#include <inttypes.h>
4

5
int main()
6
{
7
  const unsigned char pData[4] = {219, 15, 73, 64};
8

9
  float dResult;
10
  *(uint32_t*)&dResult = (uint32_t)((pData[3] << 24) | (pData[2] << 16) | (pData[1] << 8) | (pData[0]));
11

12
  printf("Value: %f\n", dResult);
13

14
  return 0;
15
}
16

17
$ rm -f main ; gcc -o main main.c
18

19
$ ./main 
20
Value: 3.141593

..will man aber nicht machen (gcc warnt auch (vollkommen zurecht) sobald 
man die Warnungen nicht unterdrückt und Optimierungen anfordert).
#3195653
Lesenswert?
• ▲
▼
Gäst_5 schrieb:

> Dazu habe ich mir folgendes gedacht:
>
> int i,j,k,l;
> float d;
>
> [...]
>
> d = (l<<24) | (k<<16) | (j<<8) | i;

> Leider funktioniert es nicht, bzw es wird eine falsche float Zahl
> angezeigt.

Die passende Lösung über memcpy wurde ja schon gepostet, deshalb nur 
für's Verständnis:

Der obige Code erzeugt aus den vier Bytes eine 32-Bit Integerzahl, die 
dann in eine Floatzahl gecastet wird.
Die einzelnen Bits, die in den vier Bytes enthalten sind und für Float 
eine völlig andere Bedeutung haben als für Integer (Exponent, Mantisse 
und Vorzeichen) werden so erst mal nach den Integer-Regeln 
(fehl)interpretiert. Diese fehlinterpretierte Integer-Zahl wird dann 
korrekt nach float konvertiert.

Das vermeidet man dadurch, dass man den Compiler die Zahl erst gar nicht 
interpretieren lässt wie beim Beispiel mit memcopy oder beim Beispiel 
von g457 über Adressoperationen (referenzieren/dereferenzieren).

Gruß,
Bernd
#3195837
Lesenswert?
• ▲
▼
amateur schrieb:
> @g457
>
> Ich schätze mal auf das:
> (uint32_t)((...)|(...)|(...)|...)
> kommt es an.
>
> Es zwingt den Compiler erst die Zahl zusammenzustellen und dann fließen
> zu lassen.
Nein - es kommt darauf an zu verhindern, dass der Compiler das Konstrukt 
aus den vier Bytes als Integert interpretiert und dann zwangsweise 
falsch nach float konvertiert.

> Die vielen Zeiger verwirren nur.
Das stimmt - insbesondere Anfänger tun sich damit schwer. Nötig sind sie 
aber trotzdem wenn man nicht über memcpy() gehen will.

Gruß,
Bernd

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.