C语言 使用 c - printf 将 ieee 754 浮点数转换为十六进制

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2941095/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:32:25  来源:igfitidea点击:

Convert ieee 754 float to hex with c - printf

cfloating-pointieee-754

提问by Michael

Ideally the following code would take a float in IEEE 754 representation and convert it into hexadecimal

理想情况下,以下代码将采用 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);
}

I'm not too sure what's going wrong. It's converting the number into a hexadecimal number, but a very wrong one.

我不太确定出了什么问题。它正在将数字转换为十六进制数,但这是一个非常错误的数字。

123.1443 gives 40000000
43.3     gives 60000000
8        gives 0

so it's doing something, I'm just not too sure what.

所以它正在做某事,我只是不太确定是什么。

Help would be appreciated

帮助将不胜感激

回答by James McNellis

When you pass a floatas an argument to a variadic function (like printf()), it is promoted to a double, which is twice as large as a float(at least on most platforms).

当您将 afloat作为参数传递给可变参数函数(如printf())时,它会被提升为 a double,它是 a 的两倍float(至少在大多数平台上)。

One way to get around this would be to cast the floatto an unsigned intwhen passing it as an argument to printf():

解决此问题的一种方法floatunsigned int在将其作为参数传递给时将其强制转换为printf()

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

This is also more correct, since printf()uses the format specifiers to determine how large each argument is.

这也更正确,因为printf()使用格式说明符来确定每个参数的大小。

Technically, this solution violates the strict aliasing rule. You can get around this by copying the bytes of the floatinto an unsigned intand then passing that to printf():

从技术上讲,此解决方案违反了严格的别名规则。您可以通过将 的字节复制float到 anunsigned int然后将其传递给来解决此问题printf()

unsigned int ui;
memcpy(&ui, &f, sizeof (ui));

printf("hex is %x", ui);

Both of these solutions are based on the assumption that sizeof(int) == sizeof(float), which is the case on many 32-bit systems, but isn't necessarily the case.

这两种解决方案都基于以下假设,sizeof(int) == sizeof(float)在许多 32 位系统上都是这种情况,但不一定是这种情况。

回答by drawnonward

When supported, use %a to convert floating point to a standard hexadecimal format. Here is the only documentI could find that listed the %a option.

如果支持,请使用 %a 将浮点数转换为标准的十六进制格式。这是我能找到的唯一列出 %a 选项的文档

Otherwise you must pull the bits of the floating point value into an integer type of known size. If you know, for example, that both float and int are 32 bits, you can do a quick cast:

否则,您必须将浮点值的位转换为已知大小的整数类型。例如,如果您知道 float 和 int 都是 32 位,则可以进行快速转换:

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

If you want to be less dependent on size, you can use a 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 );

The order of the loop would depend on the architecture endianness. This example is big endian.

循环的顺序将取决于架构字节序。这个例子是大端。

Either way, the floating point format may not be portable to other architectures. The %a option is intended to be.

无论哪种方式,浮点格式可能无法移植到其他体系结构。%a 选项旨在。

回答by Anders Jorsal

HEX to Float

十六进制浮动

I spend quite a long time trying to figure out how to convert a HEX input from a serial connection formatted as IEE754 float into float. Now I got it. Just wanted to share in case it could help somebody else.

我花了很长时间试图弄清楚如何将 HEX 输入从格式化为 IEE754 浮点数的串行连接转换为浮点数。现在我明白了。只是想分享,以防它可以帮助其他人。

#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

}

Output:

输出:

Raw1: 508C
Raw2: 436A
HEX: 0X436A508C
Float: 234.314636

回答by Anders Jorsal

This approach always worked pretty fine to me:

这种方法对我来说总是很好:

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

回答by Christopher Schneider

Stupidly simple example:

愚蠢的简单例子:

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

Pretty obvious solution when I figured it out. No bit masking, memcpy, or other tricks necessary.

当我想出来时,非常明显的解决方案。不需要位掩码、memcpy 或其他技巧。

In the above example, it was for a specific purpose and I knew floats were 32 bits. A better solution if you're unsure of the system:

在上面的例子中,它是出于特定目的,我知道浮点数是 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;
}

回答by bliako

How about this:?

这个怎么样:?

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

回答by aemre

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

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

Convert Hex to Double Convert Double to Hex

将十六进制转换为双精度 将双精度转换为十六进制

this codes working IEEE 754 floating format.

此代码适用于 IEEE 754 浮动格式。

回答by Mike McClosky

What finally worked for me (convoluted as it seems):

最终对我有用的东西(看起来很复杂):

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