Reputation: 1048
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.
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).
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
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:
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.
--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.
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);
Upvotes: 3
Views: 55785
Reputation: 46365
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 topic for 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.
Upvotes: 16
Reputation: 1582
If you are permitted to use library functions, try atoi(arr) or 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...
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:
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... */
}
Upvotes: 2
Reputation: 7204
If the input
is in the form: "0x......" then
float f;
long l;
l = strtol(input, (char**)NULL, 16);
f = (float)l;
printf("%f", f);
valter
Upvotes: 0
Reputation: 416
You'll need to use either multiplication or bit operations. After you do your bounds/hex checking you described, do something like this:
float x = 0;
for(i=0;i<8;i++)
{
x += getDecimalValue(inputArray[i+2]) << (4*(7-i))
}
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.
Upvotes: 0