web-dev-qa-db-fra.com

Convertir ieee 754 float en hex avec c - printf

Idéalement, le code suivant prendrait un float dans la représentation IEEE 754 et le convertirait en hexadécimal.

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);
}

Je ne suis pas trop sûr de ce qui ne va pas. Il convertit le nombre en un nombre hexadécimal, mais très faux.

123.1443 gives 40000000
43.3     gives 60000000
8        gives 0

donc ça fait quelque chose, je ne sais pas trop quoi.

Une aide serait appréciée

17
Michael

Lorsque vous passez une float en tant qu'argument à une fonction variadique (telle que printf()), elle est promue en une double, qui est deux fois plus grande qu'une float (au moins sur la plupart des plates-formes).

Une façon de contourner ce problème consiste à transtyper la float en unsigned int en le transmettant comme argument à printf():

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

Ceci est également plus correct, puisque printf() utilise les spécificateurs de format pour déterminer la taille de chaque argument.

Techniquement, cette solution enfreint la règle de crénelage strict . Vous pouvez contourner ce problème en copiant les octets de float dans un unsigned int, puis en les passant à printf():

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

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

Ces deux solutions sont basées sur l'hypothèse que sizeof(int) == sizeof(float), ce qui est le cas sur de nombreux systèmes 32 bits, mais ce n'est pas nécessairement le cas.

26
James McNellis

Lorsque cela est pris en charge, utilisez% a pour convertir le nombre à virgule flottante au format hexadécimal standard. Voici le seul document Je pourrais trouver que répertorié le% une option.

Sinon, vous devez extraire les bits de la valeur à virgule flottante dans un type entier de taille connue. Si vous savez, par exemple, que float et int sont tous deux 32 bits, vous pouvez effectuer une conversion rapide:

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

Si vous voulez être moins dépendant de la taille, vous pouvez utiliser une union:

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 );

L'ordre de la boucle dépend de l'endianité de l'architecture. Cet exemple est big endian.

Dans les deux cas, le format de virgule flottante peut ne pas être portable pour d'autres architectures. Le% une option est destiné à être.

12
drawnonward

HEX to Float

Je passe assez de temps à essayer de comprendre comment convertir une entrée HEX à partir d'une connexion série au format IEE754 float en float. Maintenant j'ai compris. Je voulais juste partager au cas où cela pourrait aider quelqu'un d'autre.

#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

}

Sortie:

Raw1: 508C
Raw2: 436A
HEX: 0X436A508C
Float: 234.314636
3
Anders Jorsal

Exemple stupidement simple:

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;
}

Solution assez évidente quand je l'ai compris. Aucun bit de masquage, mémoire ou autre astuce nécessaire.

Dans l'exemple ci-dessus, c'était pour un but spécifique et je savais que les flottants étaient en 32 bits. Une meilleure solution si vous n'êtes pas sûr du système:

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;
}
2

Cette approche a toujours bien fonctionné pour moi:

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
user3297304

Que dis-tu de ça:?

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");
}
1
bliako

https://github.com/aliemresk/ConvertD2H/blob/master/main.c

Convertir Hex en Double Convertir Double en Hex

ce code fonctionne au format flottant IEEE 754.

1
aemre

Ce qui a finalement fonctionné pour moi (aussi compliqué que cela puisse paraître):

#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);
}
0
Mike McClosky