Reputation: 39
I am trying to understand the process of converting a hexadecimal number to its decimal equivalent, in particular when converting each hexadecimal digit to its decimal value.
Say when the digit i
of hexVal equals any characters ranging from '0' to '9', its decVal equals the hexVal subtracted by 48 and then timed by the digitBase:
if ((hexVal[i] >= '0') && (hexVal[i] <= '9')) {
decVal += (hexVal[i] - 48) * digitBase;
...
}
I understand that 48 is ASCII value of '0'.
What I am in doubt with is where the values 55 and 87 come from when digit i
of hexVal equals the ranges 'A' to 'F' and 'a' to 'f':
else if ((hexVal[i] >= 'A') && (hexVal[i] <= 'F')) {
hexToDec += (hexVal[i] - 55) * digitBase;
...
}
and
else if ((hexVal[i] >= 'a') && (hexVal[i] <= 'f')) {
hexToDec += (hexVal[i] - 87) * digitBase;
...
}
The code blocks above are extracted from the following function which works well to convert hexadecimal numbers to their equivalent decimals.
int conv_hex_to_dec(char hexVal[]) {
int hexToDec = 0;
int len = strlen(hexVal);
int digitBase = 1;
// Extract hex characters as digits from last character
for (int i = len - 1; i >= 0; i--) {
if ((hexVal[i] >= '0') && (hexVal[i] <= '9')) {
hexToDec += (hexVal[i] - 48) * digitBase;
digitBase = digitBase * 16;
}
else if ((hexVal[i] >= 'A') && (hexVal[i] <= 'F')) {
hexToDec += (hexVal[i] - 55) * digitBase;
digitBase = digitBase * 16;
}
else if ((hexVal[i] >= 'a') && (hexVal[i] <= 'f')) {
hexToDec += (hexVal[i] - 87) * digitBase;
digitBase = digitBase * 16;
}
else {
printf("Invalid hex val");
}
}
return hexToDec;
}
Any explanation will be much appreciated.
Thanks.
Upvotes: 1
Views: 784
Reputation: 224917
This is a prime example of why "magic numbers" in code are bad.
This code makes the assumption that the character encoding is ASCII. The relevant numbers are:
'0'
'A'
'a'
So in this line of code:
decVal += (hexVal[i] - 48) * digitBase;
It is subtracting the ASCII code of hexVal[i]
from the ASCII code for '0'
. This converts a character in the range '0'
to '9'
to a value in the range 0 to 9.
Similarly, this:
hexToDec += (hexVal[i] - 55) * digitBase;
Subtracting the ASCII code of hexVal[i]
from the ASCII code of 'A'
and adds 10, This converts a character in the range 'A'
to 'F'
to a value in the range 10 to 15. Similarly, the check with 87, this converts a character in the range 'a'
to 'f'
to a value in the range 10 to 15.
A better way to write this would be:
if ((hexVal[i] >= '0') && (hexVal[i] <= '9')) {
hexToDec += (hexVal[i] - '0') * digitBase;
digitBase = digitBase * 16;
}
else if ((hexVal[i] >= 'A') && (hexVal[i] <= 'F')) {
hexToDec += (hexVal[i] - 'A' + 10) * digitBase;
digitBase = digitBase * 16;
}
else if ((hexVal[i] >= 'a') && (hexVal[i] <= 'f')) {
hexToDec += (hexVal[i] - 'a' + 10) * digitBase;
digitBase = digitBase * 16;
}
As it is more clear to the reader what the intention is.
Upvotes: 2
Reputation: 49896
48 is the ASCII code for '0'; the ASCII codes for 'A' and 'a' are 65 (55 = 65-10) and 97 (87 = 97 - 10) respectively.
Upvotes: 0