I have a text file with hexadecimal values. Now I need to convert the hexadecimal value to binary and need to save it on another file. But I don't know how to convert the hexadecimal value to a binary string! Please help...
-
You can try it like this: johnsantic.com/comp/htoi.htmlAndrija Sucevic– Andrija Sucevic2011-12-18 11:29:15 +00:00Commented Dec 18, 2011 at 11:29
-
5homework? And I'm sure you don't mean values but representations: the values are the same regardless of how they are represented.pmg– pmg2011-12-18 11:29:20 +00:00Commented Dec 18, 2011 at 11:29
-
1@pmg:ya i was doing some thing like a home work. Actually i converted a image file to hexadecimal file. Now i need to create the image from that hexadecimal file.Midhun MP– Midhun MP2011-12-18 11:36:26 +00:00Commented Dec 18, 2011 at 11:36
-
1@StanlyMoses: Read the questions carefully before closing it as duplicate, this ask how to convert hex to binary the other one asks how to convert binary to hex.Midhun MP– Midhun MP2016-02-18 12:57:29 +00:00Commented Feb 18, 2016 at 12:57
8 Answers
It's quite easy, really, because the translation goes digit-by-digit.
0 - 0000
1 - 0001
2 - 0010
3 - 0011
4 - 0100
5 - 0101
6 - 0110
7 - 0111
8 - 1000
9 - 1001
A - 1010
B - 1011
C - 1100
D - 1101
E - 1110
F - 1111
So, for example, the hex number FE2F8 will be 11111110001011111000 in binary
1 Comment
const char input[] = "..."; // the value to be converted
char res[9]; // the length of the output string has to be n+1 where n is the number of binary digits to show, in this case 8
res[8] = '\0';
int t = 128; // set this to s^(n-1) where n is the number of binary digits to show, in this case 8
int v = strtol(input, 0, 16); // convert the hex value to a number
while(t) // loop till we're done
{
strcat(res, t < v ? "1" : "0");
if(t < v)
v -= t;
t /= 2;
}
// res now contains the binary representation of the number
As an alternative (this assumes there's no prefix like in "0x3A"):
const char binary[16][5] = {"0000", "0001", "0010", "0011", "0100", ...};
const char digits = "0123456789abcdef";
const char input[] = "..." // input value
char res[1024];
res[0] = '\0';
int p = 0;
while(input[p])
{
const char *v = strchr(digits, tolower(input[p++]));
if (v)
strcat(res, binary[v - digits]);
}
// res now contains the binary representation of the number
8 Comments
digits is correct? Or wher do you get that error?long v = strtol({input[p++], 0}, NULL, 16); strcat(res, binary[v]);There are many ways to solve this question that use some arithmetics to convert from ascii character ranges 0-9 and a-f (or A-F) to binary. I wanted to find a solution which only uses a lookup table and benchmark that against a solution that uses arithmetics instead. Strangly enough, none of the answers above implement a purely arithmetic solution and some answers even assume that "converting to binary" means converting to a ascii string of characters "0" and "1".
Lets first do some setups. Firstly, we want to have the whole test data in memory so that we avoid disk I/O influencing the test. Here is how I create a header with a character array "testdata" of 104857600 bytes, roughly 105 MB. As the question was how to convert files, our implementation should be fast on large data.
$ { printf "char *testdata =\""; cat /dev/urandom \
| tr -d -c "0123456789abcdefABCDEF" \
| dd count=100 iflag=fullblock bs=1M; printf "\";\n" } > testdata.h
Next, we create the lookup tables. I see two possible ways to solve this with a lookup table. Either the lookup table maps individual ascii hex characters to half bytes or it maps two hex characters to a full byte. In the former case, the lookup table has to have 256 entries. In the latter case, the lookup table has to have 256*256=65536 entries. We can reduce the size of the latter by realizing that the first bit of the first byte will never be used. So we only need a lookup table of 128*256=32768 entries. Since that solution also requires an additional calculation step (applying a bitmask) we will benchmark both. We end up with the following test cases:
- arithmetic solution
- 256 entries lookup table
- 32768 entries lookup table
- 65536 entries lookup table
The first lookup table is easy to generate using some python:
#!/usr/bin/env python
import sys,struct
sys.stdout.write("unsigned char base16_decoding_table1[256] = {\n")
for i in xrange(256):
try:
j = str(int(chr(i), 16))
except:
j = '0'
sys.stdout.write(j+',')
sys.stdout.write("};\n")
sys.stdout.write("\n")
l = 128*256*["0"]
for a in ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F']:
for b in ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F']:
l[struct.unpack("<H", a+b)[0]] = str(int(a+b, 16))
line = "unsigned char base16_decoding_table2[%d] = {"%(128*256)
for e in l:
line += e+","
if len(line) > 70:
sys.stdout.write(line+"\n")
line = ""
sys.stdout.write(line+"};\n")
sys.stdout.write("\n")
l = 256*256*["0"]
for a in ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F']:
for b in ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F']:
l[struct.unpack("<H", a+b)[0]] = str(int(a+b, 16))
line = "unsigned char base16_decoding_table3[%d] = {"%(256*256)
for e in l:
line += e+","
if len(line) > 70:
sys.stdout.write(line+"\n")
line = ""
sys.stdout.write(line+"};\n")
And then:
python gen.py > base16_decoding_table.h
Now we can write some C code to test.
#include <stdio.h>
#include <time.h>
#include <inttypes.h>
#include "testdata.h"
#include "base16_decoding_table.h"
#define TESTDATALEN 104857600
/* the resulting binary string is half the size of the input hex string
* because every two hex characters map to one byte */
unsigned char result[TESTDATALEN/2];
void test1()
{
size_t i;
char cur;
unsigned char val;
for (i = 0; i < TESTDATALEN; i++) {
cur = testdata[i];
if (cur >= 97) {
val = cur - 97 + 10;
} else if (cur >= 65) {
val = cur - 65 + 10;
} else {
val = cur - 48;
}
/* even characters are the first half, odd characters the second half
* of the current output byte */
if (i%2 == 0) {
result[i/2] = val << 4;
} else {
result[i/2] |= val;
}
}
}
void test2()
{
size_t i;
char cur;
unsigned char val;
for (i = 0; i < TESTDATALEN; i++) {
cur = testdata[i];
val = base16_decoding_table1[(int)cur];
/* even characters are the first half, odd characters the second half
* of the current output byte */
if (i%2 == 0) {
result[i/2] = val << 4;
} else {
result[i/2] |= val;
}
}
}
void test3()
{
size_t i;
uint16_t *cur;
unsigned char val;
for (i = 0; i < TESTDATALEN; i+=2) {
cur = (uint16_t*)(testdata+i);
// apply bitmask to make sure that the first bit is zero
val = base16_decoding_table2[*cur & 0x7fff];
result[i/2] = val;
}
}
void test4()
{
size_t i;
uint16_t *cur;
unsigned char val;
for (i = 0; i < TESTDATALEN; i+=2) {
cur = (uint16_t*)(testdata+i);
val = base16_decoding_table3[*cur];
result[i/2] = val;
}
}
#define NUMTESTS 1000
int main() {
struct timespec before, after;
unsigned long long checksum;
int i;
double elapsed;
clock_gettime(CLOCK_MONOTONIC, &before);
for (i = 0; i < NUMTESTS; i++) {
test1();
}
clock_gettime(CLOCK_MONOTONIC, &after);
checksum = 0;
for (i = 0; i < TESTDATALEN/2; i++) {
checksum += result[i];
}
printf("checksum: %llu\n", checksum);
elapsed = difftime(after.tv_sec, before.tv_sec) + (after.tv_nsec - before.tv_nsec)/1.0e9;
printf("arithmetic solution took %f seconds\n", elapsed);
clock_gettime(CLOCK_MONOTONIC, &before);
for (i = 0; i < NUMTESTS; i++) {
test2();
}
clock_gettime(CLOCK_MONOTONIC, &after);
checksum = 0;
for (i = 0; i < TESTDATALEN/2; i++) {
checksum += result[i];
}
printf("checksum: %llu\n", checksum);
elapsed = difftime(after.tv_sec, before.tv_sec) + (after.tv_nsec - before.tv_nsec)/1.0e9;
printf("256 entries table took %f seconds\n", elapsed);
clock_gettime(CLOCK_MONOTONIC, &before);
for (i = 0; i < NUMTESTS; i++) {
test3();
}
clock_gettime(CLOCK_MONOTONIC, &after);
checksum = 0;
for (i = 0; i < TESTDATALEN/2; i++) {
checksum += result[i];
}
printf("checksum: %llu\n", checksum);
elapsed = difftime(after.tv_sec, before.tv_sec) + (after.tv_nsec - before.tv_nsec)/1.0e9;
printf("32768 entries table took %f seconds\n", elapsed);
clock_gettime(CLOCK_MONOTONIC, &before);
for (i = 0; i < NUMTESTS; i++) {
test4();
}
clock_gettime(CLOCK_MONOTONIC, &after);
checksum = 0;
for (i = 0; i < TESTDATALEN/2; i++) {
checksum += result[i];
}
printf("checksum: %llu\n", checksum);
elapsed = difftime(after.tv_sec, before.tv_sec) + (after.tv_nsec - before.tv_nsec)/1.0e9;
printf("65536 entries table took %f seconds\n", elapsed);
return 0;
}
Lets compile the thing:
$ gcc -O3 -g -Wall -Wextra test.c
And run it:
$ ./a.out
The result:
- arithmetic solution: 437.17 s
- 256 entries lookup table: 117.80 s
- 32768 entries lookup table: 52.33 s
- 65536 entries lookup table: 44.66 s
This we can conclude lookup tables beat arithmetic solutions any time and that wasting memory for bigger lookup tables might be worth the additional runtime.
4 Comments
void hex_binary(char * res){
char binary[16][5] = {"0000", "0001", "0010", "0011", "0100", "0101","0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110","1111"};
char digits [] = "0123456789abcdef";
const char input[] = "a9e6"; // input value
res[0] = '\0';
int p = 0;
int value =0;
while(input[p])
{
const char *v = strchr(digits, tolower(input[p]));
if(v[0]>96){
value=v[0]-87;
}
else{
value=v[0]-48;
}
if (v){
strcat(res, binary[value]);
}
p++;
}
printf("Res:%s\n", res);
}
1 Comment
The quickest and easiest way is to read the hex file and, for each character ('0' through 'F') read, do a table lookup of the equivalent (0 through 15) binary value. There are, as ever, more elegant ways but this is very straightforward, maybe something like:
switch (charval) {
case '0': binval = 0;
case '1': binval = 1;
case '2': binval = 2;
case '3': binval = 3;
....
case 'a': binval = 10;
case 'b': binval = 11;
case 'A': binval = 10;
case 'B': binval = 11;
....
case 'f': binval = 15;
case 'F': binval = 15;
default: binval = -1; // error case
}
Now you have to use shifts and IORs/ADDs to construct words of the size you want from these individual 4-bit binary values.
2 Comments
0123456789abcdef) and then get the value of a digit by using strchr() on it or i'd just use an array char [256] and use the character/digit as the index. That way you could as well use the binary representation for the digits as the values and skip additional conversion.That's my function to convert HEX to BIN, byte a byte.
void HexToBin(char hex_number, char* bit_number) {
int max = 128;
for(int i = 7 ; i >-1 ; i--){
bit_number [i] = (hex_number & max ) ? 1 : 0;
max >>=1;
}
}
and the call to the function:
void main (void){
char hex_number = 0x6E; //0110 1110
char bit_number[8]={0,0,0,0,0,0,0,0};
HexToBin(hex_number,bit_number);
for(int i = 7 ; i >-1 ; i--)
printf("%d",bit_number[i]);
printf("\n");
system("pause");
}
And here is the MSDOS answer:
01101110
Press a key to continue . . .
Quite easy!
1 Comment
#include <stdio.h>
int main()
{
long int binaryNumber,
hexadecimalNumber = 0,
j = 1,
remainder;
printf("Enter any number any binary number: ");
scanf("%ld", &binaryNumber);
while(binaryNumber != 0) {
remainder = binaryNumber % 10;
hexadecimalNumber = hexadecimalNumber + remainder * j;
j = j * 2;
binaryNumber = binaryNumber / 10;
}
printf("Equivalent hexadecimal value: %X", hexadecimalNumber);
return 0;
}