【问题标题】:What do 48 and 87 values refer to when converting hexadecimal to decimal number in C?在C中将十六进制转换为十进制时,48和87值是指什么?
【发布时间】:2020-09-06 21:15:09
【问题描述】:

我正在尝试了解将十六进制数转换为其十进制等效值的过程,尤其是在将每个十六进制数字转换为其十进制值时。

假设当hexVal的数字i等于'0'到'9'之间的任何字符时,它的decVal等于hexVal减去48然后由digitBase计时:

if ((hexVal[i] >= '0') && (hexVal[i] <= '9')) {
    decVal += (hexVal[i] - 48) * digitBase;
    ...
}

我知道 48 是 '0' 的 ASCII 值。 我怀疑的是,当 hexVal 的数字 i 等于“A”到“F”和“a”到“f”的范围时,值 55 和 87 的来源:

else if ((hexVal[i] >= 'A') && (hexVal[i] <= 'F')) {
    hexToDec += (hexVal[i] - 55) * digitBase;
    ...
}

else if ((hexVal[i] >= 'a') && (hexVal[i] <= 'f')) {
    hexToDec += (hexVal[i] - 87) * digitBase;
    ...
}

上面的代码块是从以下函数中提取的,该函数可以很好地将十六进制数转换为等效的十进制数。

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;
}

任何解释将不胜感激。

谢谢。

【问题讨论】:

  • asciitable.com 这就是为什么我们不应该使用幻数 48 而是输入 '0'
  • 这是十六进制表示转换为int的字符串。减去 ascii 值得到一个字符的实际十进制值。即 9 是 '9' - '0' 的 ascii 值
  • "以下函数可以很好地将十六进制数转换为等效的十进制数" ---> 仅限于 INT_MAX。除此之外,代码是UB。

标签: c numbers hex decimal base


【解决方案1】:

这是为什么代码中的“幻数”不好的一个典型例子。

此代码假设字符编码为 ASCII。相关数字是:

  • 48:'0' 的 ASCII 码
  • 65:'A' 的 ASCII 码
  • 97:'a' 的 ASCII 码

所以在这行代码中:

decVal += (hexVal[i] - 48) * digitBase;

它是从'0' 的 ASCII 码中减去hexVal[i] 的 ASCII 码。这会将'0''9' 范围内的字符转换为0 到9 范围内的值。

同样,这个:

hexToDec += (hexVal[i] - 55) * digitBase;

'A' 的ASCII 码中减去hexVal[i] 的ASCII 码并加10,这会将'A''F' 范围内的字符转换为10 到15 范围内的值。类似地,检查 87,这会将'a''f' 范围内的字符转换为 10 到 15 范围内的值。

更好的写法是:

    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;
    }

因为读者更清楚意图是什么。

【讨论】:

  • 感谢您的详细解释并指出良好的编码实践。
  • 假设 0-9 和 af 的字符代码都是按顺序排列的,这可能是正确的,但可能不是(考虑 EBCDIC,它在字母的代码,虽然不在 f)。
【解决方案2】:

48 是 '0' 的 ASCII 码; 'A' 和 'a' 的 ASCII 码分别是 65 (55 = 65-10) 和 97 (87 = 97 - 10)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-04
    • 2017-07-31
    • 2013-07-20
    • 2012-06-17
    • 2014-02-05
    • 2021-06-26
    • 1970-01-01
    相关资源
    最近更新 更多