2010-05-31 6 views
16

Idealen der folgende Code einen Schwimmer in IEEE 754 Darstellung nehmen würde und wandelt es in hexadezimalConvert ieee 754 Schwimmer mit c verhexen - printf

void convert() //gets the float input from user and turns it into hexadecimal 
{ 
    float f; 
    printf("Enter float: "); 
    scanf("%f", &f); 
    printf("hex is %x", f); 
} 

ich nicht sicher bin, was falsch läuft. Es konvertiert die Zahl in eine hexadezimale Zahl, aber eine sehr falsche.

123.1443 gives 40000000 
43.3  gives 60000000 
8  gives 0 

so tut es etwas, ich bin nur nicht sicher, was.

würde Hilfe

+0

'float' wird in variadischen Funktionen zum' double' befördert (siehe James McNellis 'Antwort). Probieren Sie stattdessen 'printf (" hex is% lx ", f);'. Sehen Sie für portablen Code sizeof (double) im Vergleich zu sizeof (int) und sizeof (long), um zu bestimmen, ob 'x' oder' lx' verwendet werden soll. – tomlogic

+0

Woher wissen Sie, dass es IEEE 754 ist? –

+0

@tomlogic: Für portablen Code übergeben Sie keinen Gleitkommawert an 'printf' mit einem Format, das eine Ganzzahl erfordert. Das Verhalten ist nicht definiert, auch wenn die Größen übereinstimmen. (Grüße aus 7 Jahren in der Zukunft. Fragen Sie nicht.) –

Antwort

24

geschätzt werden, wenn Sie ein float als Argument für eine variadische Funktion (wie printf()) übergeben, um es zu einem double gefördert wird, das doppelt so groß ist wie eine float (zumindest auf den meisten Plattformen).

Eine Möglichkeit, dies zu umgehen wäre die float zu einem unsigned int zu werfen, wenn sie als Argument an printf() vorbei:

printf("hex is %x", *(unsigned int*)&f); 

Dies ist auch richtig, da printf() die Formatbezeichner verwendet, um zu bestimmen, wie groß ist jedes Argument.

Technisch verletzt diese Lösung die strict aliasing rule. Sie können durch Kopieren der Bytes des float in eine unsigned int dieses Problem umgehen, und dann vorbei, das zu printf():

unsigned int ui; 
memcpy(&ui, &f, sizeof (ui)); 

printf("hex is %x", ui); 

sind Beide Lösungen basieren auf der Annahme, dass sizeof(int) == sizeof(float), was der Fall bei vielen 32-Bit Systeme, ist aber nicht unbedingt der Fall.

+1

Um die strenge Aliasing-Regel zu vermeiden, versuchen Sie * (flüchtige unsigned int *) (flüchtige float *) (&f); – Joshua

+0

Warum können Sie nicht nur printf ("hex ist% x \ n", (unsigned int) f) unter der Annahme, dass f in unsigned int passen kann. – Nyan

+4

@Nyan: Weil das die Bits nicht als vorzeichenlosen Wert uminterpretiert, das wird den Float zu konvertieren ein nicht vorzeichenbehafteter Wert (also würde 24.12 24 werden, was nicht das gewünschte Ergebnis ist.) –

12

Wenn dies unterstützt wird, verwenden Sie% a, um Gleitkommazahlen in ein hexadezimales Standardformat zu konvertieren. Hier ist der einzige document Ich könnte finden, dass die% a-Option aufgelistet.

Andernfalls müssen Sie die Bits des Gleitkommawerts in einen ganzzahligen Typ bekannter Größe ziehen. Wenn Sie wissen, zum Beispiel, dass beide Schwimmer und int sind 32 Bits, können Sie eine schnelle Besetzung tun:

printf("%08X" , *(unsigned int*)&aFloat); 

Wenn Sie auf Größe weniger abhängig sein wollen, können Sie eine Vereinigung verwenden:

union { 
    float f; 
//char c[16]; // make this large enough for any floating point value 
    char c[sizeof(float)]; // Edit: changed to this 
} u; 

u.f = aFloat; 
for (i = 0 ; i < sizeof(float) ; ++i) printf("%02X" , u.c[i] & 0x00FF); 

Die Reihenfolge der Schleife hängt von der Architekturendianess ab. Dieses Beispiel ist Big Endian.

In beiden Fällen ist das Gleitkommaformat möglicherweise nicht auf andere Architekturen portierbar. Die Option% a soll sein.

+0

+1: Ich kannte den '% nicht a 'format specifier. Jetzt fühle ich mich dumm :-) –

+0

+1 für das Wissen über% a. Warum' 'char [16]' 'und nicht' 'char [sizeof (float)]' '? –

+0

C99 ist ein anderes Dokument, das es erwähnt :-) –

1

Wie wäre es damit?

int main(void){ 
    float f = 28834.38282; 
    char *x = (char *)&f; 
    printf("%f = ", f); 

    for(i=0; i<sizeof(float); i++){ 
    printf("%02X ", *x++ & 0x0000FF); 
    } 

    printf("\n"); 
} 
3

HEX

Ich verbringe ziemlich viel Zeit Float versuchen, herauszufinden, wie ein HEX-Eingang von einem seriellen Anschluss als IEE754 Schwimmer in float formatiert zu konvertieren. Jetzt hab ich es verstanden. Ich wollte nur teilen, falls es jemand anderem helfen könnte.

#include <stdio.h> 
#include <stdlib.h> 
int main(int argc, char *argv[]) 
{ 

    uint16_t tab_reg[64]     //declare input value recieved from serial connection 
    union IntFloat { int32_t i; float f; }; //Declare combined datatype for HEX to FLOAT conversion 
    union IntFloat val;      
    int i; 
    char buff[50];       //Declare buffer for string 

    i=0; 

    //tab_reg[i]=0x508C;     //to test the code without a data stream, 
    //tab_reg[i+1]=0x4369;     //you may uncomment these two lines. 


    printf("Raw1: %X\n",tab_reg[i]);  //Print raw input values for debug 
    printf("Raw2: %X\n",tab_reg[i+1]);  //Print raw input values for debug 

    rs = sprintf(buff,"0X%X%X", tab_reg[i+1], tab_reg[i]); //I need to swap the words, as the response is with the opposite endianness. 
    printf("HEX: %s",buff);     //Show the word-swapped string 
    val.i = atof(buff);      //Convert string to float :-) 
    printf("\nFloat: %f\n", val.f);   //show the value in float 

} 

Ausgang:

Raw1: 508C 
Raw2: 436A 
HEX: 0X436A508C 
Float: 234.314636 
2

Dieser Ansatz immer mir funktionierte ziemlich gut:

union converter{ 
float f_val; 
unsigned int u_val; 
}; 

union converter a; 
a.f_val = 123.1443f; 
printf("my hex value %x \n", a.u_val); 
2

Stupidly einfaches Beispiel:

unsigned char* floatToHex(float val){ 
    unsigned char* hexVals = malloc(sizeof(float)); 
    hexVals[0] = ((unsigned char*)&val)[0]; 
    hexVals[1] = ((unsigned char*)&val)[1]; 
    hexVals[2] = ((unsigned char*)&val)[2]; 
    hexVals[3] = ((unsigned char*)&val)[3]; 
    return hexVals; 
} 

recht nahe liegende Lösung, wenn ich es dachte, aus. Keine Bitmaskierung, Memcpy oder andere Tricks notwendig.

In dem obigen Beispiel war es für einen bestimmten Zweck und ich wusste Floats waren 32 Bits. Eine bessere Lösung, wenn Sie des Systems nicht sicher sind:

unsigned char* floatToHex(float val){ 
    unsigned char* hexVals = malloc(sizeof(float)); 
    for(int i = 0; i < sizeof(float); i++){ 
     hexVals[i] = ((unsigned char*)&val)[i]; 
    } 
    return hexVals; 
} 
0

Was für mich endlich geklappt (gefaltet, wie es scheint):

#include <stdio.h> 
int main((int argc, char** argv) 
{ 
    float flt = 1234.56789; 
    FILE *fout; 
    fout = fopen("outFileName.txt","w"); 
    fprintf(fout, "%08x\n", *((unsigned long *)&flt); 
     /* or */ 
    printf("%08x\n", *((unsigned long *)&flt); 
} 
Verwandte Themen