Преобразовать ieee 754 float в hex с c - printf
В идеале следующий код будет принимать float в представлении IEEE 754 и преобразовать его в шестнадцатеричный
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);
}
Я не слишком уверен, что происходит не так. Он преобразует число в шестнадцатеричное число, но очень неправильное.
123.1443 gives 40000000
43.3 gives 60000000
8 gives 0
поэтому он что-то делает, я просто не уверен, что.
Помощь будет оценена
Ответы
Ответ 1
Когда вы передаете float
в качестве аргумента в вариационную функцию (например, printf()
), ее повышают до double
, которая вдвое больше, чем float
(по крайней мере, на большинстве платформ).
Одним из способов обойти это было бы приведение float
к unsigned int
при передаче его в качестве аргумента printf()
:
printf("hex is %x", *(unsigned int*)&f);
Это также более корректно, поскольку printf()
использует спецификаторы формата, чтобы определить, насколько велики каждый аргумент.
Технически это решение нарушает правило строгого псевдонимов. Вы можете обойти это, скопировав байты float
в unsigned int
, а затем перейдя к printf()
:
unsigned int ui;
memcpy(&ui, &f, sizeof (ui));
printf("hex is %x", ui);
Оба этих решения основаны на предположении, что sizeof(int) == sizeof(float)
, что имеет место во многих 32-битных системах, но это не обязательно так.
Ответ 2
При поддержке используйте% a для преобразования с плавающей точкой в стандартный шестнадцатеричный формат. Вот только документ, который я мог найти, указав опцию% a.
В противном случае вы должны вывести биты значения с плавающей запятой в целочисленный тип известного размера. Если вы знаете, например, что float и int - 32 бита, вы можете быстро выполнить:
printf( "%08X" , *(unsigned int*)&aFloat );
Если вы хотите быть менее зависимым от размера, вы можете использовать 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 );
Порядок цикла будет зависеть от конъюнктуры архитектуры. Этот пример является большим аргументом.
В любом случае формат с плавающей точкой не может быть переносимым для других архитектур. Предполагается, что опция% a.
Ответ 3
HEX to Float
Я потратил довольно много времени на то, чтобы выяснить, как преобразовать вход HEX из последовательного соединения, отформатированного как float IEE754, в float. Теперь я понял. Просто хотел поделиться тем, что может помочь кому-то другому.
#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
}
Вывод:
Raw1: 508C
Raw2: 436A
HEX: 0X436A508C
Float: 234.314636
Ответ 4
Этот подход всегда работал очень хорошо:
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);
Ответ 5
Глупо простой пример:
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;
}
Довольно очевидное решение, когда я понял это. Нет необходимости в маскировке, memcpy или других трюках.
В приведенном выше примере это было для определенной цели, и я знал, что поплавки были 32 бит. Лучшее решение, если вы не уверены в системе:
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;
}
Ответ 6
Как насчет этого:?
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");
}
Ответ 7
Что, наконец, сработало для меня (свернулось, как кажется):
#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);
}
Ответ 8
https://github.com/aliemresk/ConvertD2H/blob/master/main.c
Преобразование шестнадцатеричного кода в двойное
Преобразование Double to Hex
этот код работает с плавающим форматом IEEE 754.