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