C语言 在C中将十六进制转换为浮点数,反之亦然

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21323099/
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 10:40:27  来源:igfitidea点击:

Convert a hexadecimal to a float and viceversa in C

carraysfloating-pointhex

提问by macalaca

I'm trying to write an algorithm to convert a hexadecimal number to a floating point number and vice versa. This is part of an assignment, the program is supposed to receive either an 8 digit hexadecimal number that starts with '0x' or a floating point number, and using the computer's 'built in IEEE 754 capabilities' convert the number to hex or float. The code should be in C.

我正在尝试编写一种算法来将十六进制数转换为浮点数,反之亦然。这是作业的一部分,程序应该接收以“0x”开头的 8 位十六进制数或浮点数,并使用计算机的“内置 IEEE 754 功能”将数字转换为十六进制或浮点数。代码应该是 C 语言。

My approach is the following. Store the input by the user as a string. Pass the input char array to a method that checks if it's a hexadecimal number by checking the first two positions of the array, which should be 0 and X (assume all hex numbers are passed this way). If this is the case, then I check that the hex is in the appropriate form, i.e not too many digits or numbers outside the 0-15 range (also considering the ABCDEF convention).

我的方法如下。将用户的输入存储为字符串。将输入字符数组传递给一个方法,该方法通过检查数组的前两个位置来检查它是否是十六进制数,这两个位置应该是 0 和 X(假设所有十六进制数都以这种方式传递)。如果是这种情况,那么我检查十六进制是否采用适当的形式,即 0-15 范围之外的数字或数字没有太多(也考虑 ABCDEF 约定)。

So, my problem is, I don't know how to turn this array back into a number that I can use to convert to floating point. I thought about using sscanf to turn it back into a float but I don't know enough C and haven't found any good sources online

所以,我的问题是,我不知道如何将这个数组转换回一个我可以用来转换为浮点数的数字。我想过使用 sscanf 将其变回浮点数,但我对 C 的了解不够,也没有在网上找到任何好的资源

Can somebody point me in the right direction? I also thought about storing the user input both as a string and a number at the same time, but I am not sure if this is possible.

有人可以指出我正确的方向吗?我还考虑过将用户输入同时存储为字符串和数字,但我不确定这是否可行。

Here are the two form checking functions and the incomplete main method:

下面是两个表单检查函数和不完整的 main 方法:

int is_hex(char arr[])
{
    if (arr[0] == '0' && (arr[1] == 'x' || arr[1] == 'X')) {
        return 1;
    }
    return 0;
}

int check_if_good(char arr[])
{
    if (is_hex(arr)) {
        int len = strlen(arr);
        for (int i = 2; i < len; i++) {
            if ((arr[i] > 'f' && arr[i] <= 'z') || (arr[i] > 'F' && arr[i] <= 'Z')) {
                return 0;
            }
        }
    }

    return 1;
}

int main(int argc, const char * argv[])
{
    float x;
    char input[30];
    scanf("%s", input);
    printf("%s", input);
    return 0;
}

If somebody could also tell me the basics of what '%x' means i would really appreciate it. From what I understand it lets me collect numbers in hexadecimal form, but can i store them in ints and floats? Thank you very much for your help.

如果有人也能告诉我 '%x' 的基本含义,我将不胜感激。据我所知,它可以让我以十六进制形式收集数字,但我可以将它们存储在整数和浮点数中吗?非常感谢您的帮助。

--Edit: Extra code for floris. I'm trying to solve this problem without using any extra libraries, so you can't use the stdint lib.

-- 编辑: floris 的额外代码。我试图在不使用任何额外库的情况下解决此问题,因此您无法使用 stdint 库。

char input[30];
scanf("%s", input);
if(check_if_good(input)){  //Ignore this if-statement.
    printf("Input is in hex form");
}
int num = convert_hex_string(input); // this function works perfectly. It return the int form of the hex.
double f = *((double*)&num);
printf("%f\n", f);

回答by Floris

If you actually want to know what floating point number is represented by a particular hex string, you can convert the string to an integer, then look at the address pretending that it contains a floating point number. Here's how that would work:

如果你真的想知道一个特定的十六进制字符串代表什么浮点数,你可以将字符串转换为整数,然后假装它包含一个浮点数查看地址。这是如何工作的:

#include <stdint.h>
#include <stdio.h>

int main(void) {
  char myString[]="0x3f9d70a4";
  uint32_t num;
  float f;
  sscanf(myString, "%x", &num);  // assuming you checked input
  f = *((float*)&num);
  printf("the hexadecimal 0x%08x becomes %.3f as a float\n", num, f);
}

This produces as output

这产生作为输出

the hexadecimal 0x3f9d70a4 becomes 1.230 as a float

As expected. See my answer to your other question about a related topicfor more details.

正如预期的那样。有关更多详细信息,请参阅我对有关相关主题的其他问题的回答

It should also be easy to see how you can do the above in reverse - start with a floating point number, and get the hexadecimal representation.

也应该很容易看出如何反向执行上述操作 - 从浮点数开始,并获得十六进制表示。

回答by maharvey67

If you are permitted to use library functions, try atoi(arr) or sscanf(arr+2, "%x", &num)

如果您被允许使用库函数,请尝试 atoi(arr) 或 sscanf(arr+2, "%x", &num)

If you want to parse the string manually, think about how you'd convert a decimal number. For example, converting "2987" to an integer...

如果您想手动解析字符串,请考虑如何转换十进制数。例如,将“2987”转换为整数...

int n = 0;
n += 1000 * 2;
n += 100  * 9;
n += 10   * 8;
n += 1    * 7;

Now apply the technique to hexadecimal. Here is a code snippet to do a single ascii character:

现在将该技术应用于十六进制。这是一个执行单个 ascii 字符的代码片段:

int char_to_int(char c) {
   if (c >= '0' && c <= '9') return c - '0';
   if (c >= 'A' && c <= 'F') return c - 'A' + 10;
   return 0; /* oops, something else... */
}

回答by chux - Reinstate Monica

To convert a string of hexadecimal or floating point characters in to a float:

要将十六进制或浮点字符字符串转换为float

float StringToFloat(const char *s) {
  // OP's is_hex()
  if ((*s == '0') && ((*s == 'X') || (*s == 'x'))) {
    unsigned long ul = strtoul(d, NULL, 16);
    return  (float) ul;
  }
  double d = atof(s, NULL);
  return (float) d;
}
// Error handling omitted.

To convert a floatto a string of hexadecimal characters:

要将 a 转换float为十六进制字符串:

// return 1 on error
int StringToFloat(char *dest, float x) {
  float y = roundf(x);
  if ((x != y) || (y >= 4294967296.0f) || (y < 0.0f)) return 1;
  sprintf(dest, "0x%lx", (unsigned long) y);
  return 0;
}


To convert a string of hexadecimal characters into a floator unsigned longwithout library functions.
(Does notassume ASCII).

将一串十六进制字符转换为有floatunsigned long无库函数。
假设 ASCII)。

// Substitute unsigned long for float as desired.
// Error return handing is then different.
float HexStringToFloat(const char *s) {
  if ((*s != '0') || ((*s != 'X') && (*s != 'x'))) {
    return NAN;  // Not-a-number macro from math.h
  }
  float x = 0;
  int ch;
  while ((ch = *s++) != '
float f;
long l;

l = strtol(input, (char**)NULL, 16);
f = (float)l;

printf("%f", f);
') { static const char HexDigit[] = "0123456789ABCDEFabcdef"; int i = 0; while (1) { if (HexDigit[i] == '
float x = 0;
for(i=0;i<8;i++)
{
 x += getDecimalValue(inputArray[i+2]) << (4*(7-i))
}
') return NAN; if (HexDigit[i] == ch) break; i++; } if (i >= 16) i -= 6; x *= 16; x += i; } return x; }

回答by γηρ?σκω δ' αε? πολλ? διδασκ?με

If the inputis in the form: "0x......" then

如果input是这样的形式:“0x......”那么

##代码##

valter

瓦尔特

回答by George

You'll need to use either multiplication or bit operations. After you do your bounds/hex checking you described, do something like this:

您需要使用乘法或位运算。在完成您描述的边界/十六进制检查后,请执行以下操作:

##代码##

This is untested code & you will need to do the conversion from char to decimal value (A=10, B=11 ect). That bitwise operation is the same as multiplying the decimal equivalent of the hex character by 2^numberOfBits. This answer is assuming the leftmost hex is the most significant (Big endian), reverse the operation for little endianess.

这是未经测试的代码,您需要将字符转换为十进制值(A=10,B=11 等)。该按位运算与将十六进制字符的十进制等效值乘以 2^numberOfBits 相同。这个答案假设最左边的十六进制是最重要的(大端),反转小端的操作。