forumflaneur
forumflaneur

Reputation: 39

What do 48 and 87 values refer to when converting hexadecimal to decimal number in C?

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

Answers (2)

dbush
dbush

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:

  • 48: the ASCII code for '0'
  • 65: the ASCII code for 'A'
  • 97: the ASCII code for '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

Scott Hunter
Scott Hunter

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

Related Questions