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
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 float
unsigned 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.
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.
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
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;
}
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");
}
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.
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);
}