Conversion IEEE 754 float en hex avec C-printf

idéalement le code suivant prendrait un flottant 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 va mal. Il convertit le nombre en un nombre hexadécimal,mais un très mauvais.

123.1443 gives 40000000
43.3     gives 60000000
8        gives 0

donc il fait quelque chose, Je ne suis pas trop sûr de quoi.

Aide serait appréciée

17
demandé sur James McNellis 2010-05-31 06:27:12

8 réponses

quand vous passez un float comme argument à une fonction variadique (comme printf()), il est promu à un double, qui est deux fois plus grand qu'un

une façon de contourner cela serait de lancer le floatunsigned int en le passant comme argument à printf():

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

C'est aussi plus correct, car printf() utilise les spécificateurs de format pour déterminer la taille de chaque argument est.

Techniquement, cette solution viole la strict aliasing règle. Vous pouvez contourner cela en copiant les octets du float dans un unsigned int et en passant ensuite que 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 n'est pas nécessairement le cas.

25
répondu James McNellis 2017-05-23 12:32:11

Lorsqu'il est pris en charge, Utilisez %a pour convertir floating point en format hexadécimal standard. Ici est le seul document j'ai pu trouver qui a inscrit l' %une option.

sinon vous devez tirer les bits de la valeur de point flottant dans un type entier de taille connue. Si vous savez, par exemple, que float et int sont tous les deux 32 bits, vous pouvez lancer rapidement:

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

Si vous voulez être moins dépendante de la taille, vous pouvez utiliser un syndicat:

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

La commande de la boucle dépend de l'architecture boutisme. Cet exemple est big endian.

D'une façon ou d'une autre, le format à virgule flottante peut ne pas être portable pour d'autres architectures. Le %qu'une option est censée représenter.

12
répondu drawnonward 2010-05-31 18:54:04

HEX Flotter

je passe beaucoup de temps à essayer de comprendre comment convertir une entrée HEX à partir d'une connexion série formatée alors que IEE754 flotte en float. Maintenant je l'ai eu. Je voulais juste partager au cas où ça 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
répondu Anders Jorsal 2012-10-06 12:35:27

Cette approche a toujours travaillé très bien 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
répondu 2014-02-11 13:07:06

Bêtement exemple 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;
}
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
répondu Christopher Schneider 2015-11-08 03:57:13

Que Diriez-vous de ceci:?

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
répondu bliako 2012-11-06 00:37:07

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

convertir Hex en Double Convertir Double en Hex

ce code utilise le format flottant IEEE 754.

1
répondu aemre 2017-01-23 12:10:57

Ce qui a finalement fonctionné pour moi (alambiqué comme il semble):

#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
répondu Mike McClosky 2016-11-14 23:43:24