Перевод из шестнадцатеричного числа в десятичное

Рейтинг: -2Ответов: 2Опубликовано: 21.07.2023

Помогите разобраться. Почему если я заменю строку-1 на строку-2 то результат будет неверным. Как понять логику вот этой строки?

HEX.indexOf(hexNumber.charAt(i));             

Для примера, если открыть оба закомментированных println и посмотреть на вывод, результаты будут одинаковые. Вот тут-то я и завис. Зачем этот HEX.indexOf()?

public static int toDecimal(String hexNumber) {
    int decimalNumber = 0;
    for (int i = 0; i < hexNumber.length(); i++) {
        decimalNumber = 16 * decimalNumber + HEX.indexOf(hexNumber.charAt(i));    //строка-1
//      decimalNumber = 16 * decimalNumber + hexNumber.charAt(i);                   строка-2 
//      System.out.println("hexNumber.charAt(i) = " + hexNumber.charAt(i)); 
//      System.out.println("HEX.indexOf(hexNumber.charAt(i)) = " +   
    }
    return decimalNumber;
}

Ответы

▲ 0Принят

Во-первых, результаты вывода "раскомментированных" принтов будут разные для 16-ричных чисел от 0xA до 0xF.

Во-вторых, входная строка hexNumber должна быть "нормализована", то есть в ней должны содержаться либо только прописные либо только строчные буквы, иначе HEX.indexOf вернёт -1.

private static final String HEX = "0123456789ABCDEF";
    
public static int toDecimal(String hexNumber) {
    int decimalNumber = 0;
    for (int i = 0; i < hexNumber.length(); i++) {
        decimalNumber = 16 * decimalNumber + HEX.indexOf(hexNumber.charAt(i));    //строка-1
//      decimalNumber = 16 * decimalNumber + hexNumber.charAt(i); строка-2 
        System.out.println("hexNumber.charAt(i) = " + hexNumber.charAt(i));
        System.out.println("HEX.indexOf(hexNumber.charAt(i)) = " +  HEX.indexOf(hexNumber.charAt(i)));
    }
    return decimalNumber;
}
// тест
System.out.println(toDecimal("1AFc"));

Вывод:

hexNumber.charAt(i) = 1
HEX.indexOf(hexNumber.charAt(i)) = 1   // типа ок, '1' -> 1 
hexNumber.charAt(i) = A
HEX.indexOf(hexNumber.charAt(i)) = 10  // не совпадает, символ 'A' (65 = 0x41) != 10
hexNumber.charAt(i) = F
HEX.indexOf(hexNumber.charAt(i)) = 15  // не совпадает, символ 'F' (70 = 0x46) != 15
hexNumber.charAt(i) = c
HEX.indexOf(hexNumber.charAt(i)) = -1  // символ 'c' не найден! -1
6895

Результат неверный, 0x1AFc == 6908.


Обращение к HEX.indexOf можно заменить обращением к методу Character::getNumericValue, который возвращает корректные цифровые значения для символов, включая шестнадцатиричные.

public static int toDecimalFix(String hexNumber) {
    int decimalNumber = 0;
    for (char c : hexNumber.toCharArray()) {
        decimalNumber = (decimalNumber << 4) + Character.getNumericValue(c);
    }
    return decimalNumber;
}

Для проверки можно использовать стандартные методы Integer::parseInt(String str, int radix), Integer::parseUnsignedInt(String str, int radix), Integer::valueOf(String str, int radix), в которые можно передать основание системы счисления.

▲ 0

Вы же не показали, что такое HEX

Однако из кода понятно, что hexNumber.charAt(i) выделяет один символ шестнадцатеричного представления (например, "6" или "F").

А HEX.indexOf находит порядковый номер этого символа в строке (или в массиве, или к чему там ещё может применяться indexof) "0123456789ABCDEF", и таким образом даёт число, соответствующее этому символу. Это один разряд шестнадцатеричного числа. Вот это число уже используется в арифметических действиях.