simple - Convertir ieee 754 flotante a hex con c-printf
ieee 754 simple precision (8)
Idealmente, el siguiente código tomaría un flotante en la representación IEEE 754 y lo convertiría en hexadecimal
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);
}
No estoy muy seguro de lo que está pasando mal. Está convirtiendo el número en un número hexadecimal, pero uno muy equivocado.
123.1443 gives 40000000
43.3 gives 60000000
8 gives 0
entonces está haciendo algo, no estoy muy seguro de qué.
Ayuda sería apreciada
Cuando pasa un float
como argumento a una función variadica (como printf()
), se promueve a un double
, que es dos veces más grande que un float
(al menos en la mayoría de las plataformas).
Una forma de evitar esto sería convertir el float
en un unsigned int
al pasarlo como argumento a printf()
:
printf("hex is %x", *(unsigned int*)&f);
Esto también es más correcto, ya que printf()
usa los especificadores de formato para determinar qué tan grande es cada argumento.
Técnicamente, esta solución viola la regla de aliasing estricta . Puede evitar esto copiando los bytes del float
en un unsigned int
y luego pasando eso a printf()
:
unsigned int ui;
memcpy(&ui, &f, sizeof (ui));
printf("hex is %x", ui);
Ambas soluciones se basan en la suposición de que sizeof(int) == sizeof(float)
, que es el caso en muchos sistemas de 32 bits, pero no es necesariamente el caso.
Cuando sea compatible, use% a para convertir el punto flotante a un formato hexadecimal estándar. Este es el único documento que pude encontrar que enumeró la opción% a.
De lo contrario, debe extraer los bits del valor del punto flotante en un tipo entero de tamaño conocido. Si sabes, por ejemplo, que tanto float como int son 32 bits, puedes hacer un lanzamiento rápido:
printf( "%08X" , *(unsigned int*)&aFloat );
Si desea depender menos del tamaño, puede usar una unión:
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 );
El orden del ciclo dependería de la arquitectura endianness. Este ejemplo es Big Endian.
De cualquier manera, el formato de coma flotante puede no ser portátil para otras arquitecturas. La opción% a está destinada a ser.
Ejemplo estúpidamente 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;
}
Una solución bastante obvia cuando lo descubrí. Sin enmascaramiento, memcpy u otros trucos necesarios.
En el ejemplo anterior, era para un propósito específico y sabía que las carrozas eran de 32 bits. Una mejor solución si no está seguro del sistema:
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;
}
Este enfoque siempre funcionó bastante bien para mí:
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);
HEX para flotar
Dedico bastante tiempo tratando de descubrir cómo convertir una entrada HEX de una conexión en serie formateada como flotador IEE754 en flotante. Ahora lo tengo. Solo quería compartir en caso de que pudiera ayudar a alguien más.
#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
}
Salida:
Raw1: 508C
Raw2: 436A
HEX: 0X436A508C
Float: 234.314636
Lo que finalmente funcionó para mí (intrincado como parece):
#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);
}
Qué tal esto:?
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 hexadecimal a doble conversión doble a hexadecimal
esto codifica el formato flotante IEEE 754.