【问题标题】:Convert ieee 754 float to hex with c - printf使用 c - printf 将 ieee 754 浮点数转换为十六进制
【发布时间】:2011-02-25 19:59:52
【问题描述】:

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

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

我们将不胜感激

【问题讨论】:

  • float 在可变参数函数中被提升为 double(参见 James McNellis 的回答)。请改用printf("hex is %lx", f);。对于可移植代码,查看 sizeof(double) 与 sizeof(int) 和 sizeof(long) 的比较以确定是使用 x 还是 lx
  • 你怎么知道它是 IEEE 754?
  • @tomlogic:对于可移植代码,不要将浮点值传递给printf,其格式需要整数。即使大小恰好匹配,行为也是未定义的。 (来自未来 7 年的问候。不要问。)

标签: c floating-point ieee-754


【解决方案1】:

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

解决此问题的一种方法是将float 作为参数传递给unsigned int 时将其转换为unsigned int

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

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

从技术上讲,这个解决方案违反了strict aliasing rule。您可以通过将float 的字节复制到unsigned int 然后将其传递给printf() 来解决此问题:

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

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

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

【讨论】:

  • 为避免违反严格的别名规则,请尝试 *(volatile unsigned int *)(volatile float *)(&f);
  • 你为什么不能 printf("hex is %x\n",(unsigned int)f) ???假设 f 可以适应 unsigned int。
  • @Nyan:因为这不会将这些位重新解释为无符号值,所以会将浮点数转换为无符号值(因此,24.12 将变为 24,这不是预期的结果)。
  • 这个自动促销让我花了很多时间。非常沮丧:(
【解决方案2】:

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

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

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

如果你想减少对大小的依赖,可以使用联合:

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 选项的目的是。

【讨论】:

  • +1:我不熟悉 %a 格式说明符。现在我觉得很愚蠢:-)
  • +1 用于了解 %a。为什么是“char[16]”而不是“char[sizeof(float)]”?
  • C99 是另一个提到它的文件 :-)
【解决方案3】:

十六进制转浮点

我花了很长时间试图弄清楚如何将 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

}

输出:

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】:

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

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

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

          【讨论】:

            【解决方案8】:

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

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-04-02
              • 2014-06-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-09-18
              • 1970-01-01
              相关资源
              最近更新 更多