Вопрос по коду с++

162
30 марта 2018, 13:11

Здравствуйте, пытаюсь разобраться с кодом (переводит число из 10 системы в любую).

char int_symbol(int in) {
    char out[] = { '0','1','2','3','4','5','6','7','8','9',
        'A','B','C','D','E','F'};
    return out[in];
}

void ten_base(int in, int base) {
    if (in<base) {
        cout << int_symbol(in);
        return;
    }
    ten_base(in / base, base);
    cout << int_symbol(in%base);
}

in - число. base - система счисления. Понимаю, что в out написаны допустимые символы, но как определяет, например, что A=10 в 16 системе счисления?

Answer 1

Ну все довольно просто. Написать было можно и без дублирования некоторого кода, но этот алгоритм таков:

  1. Мы берем некоторое число в десятичной системе счисления и передаем его в функцию ten_base, дополнительно передав основание системы, в которой нужно вывести число.

  2. Проверяем, больше ли наше число нужного основания. Если меньше, то значит остался последний разряд - выводим его и прерываем рекурсию.

  3. Если число не меньше основания, то запускаем рекурсию с in / base - т.е. убрав младший разряд.

  4. Выводим этот самый младший разряд - in % base - остаток от деления числа на основание и будет младшим разрядом. Кстати, это число будет лежать в интервале [0; 15] для основания 16, и логично, что передав его в функцию int_symbol мы получим соответствующую цифру или букву.

Давайте теперь разберем на примере, как это работает. Возьмем число 154 и посмотрим, как оно выглядит с основанием 16.

  1. Отправляем его в ten_base - ten_base(154, 16). Проверяем. Оно явно больше основания, идем дальше.

  2. Теперь вызываем ten_base с параметрами (154 / 16, 16) - т.е. (9, 16).

  3. Делаем проверку. Ага, 9 < 16. Выводим int_symbol(9) (что будет равно девятке же) и возвращаемся. Вывод сейчас выглядит так:

    9
    
  4. Вышли из ten_base(9, 16), т.е. из вызова этой функции в пункте 2. Далее выводим int_symbol(154 % 16), т.е. int_symbol(10). int_symbol тут вернет нам A, и вывод будет выглядеть так:

    9A
    

Теперь возвращаемся из рекурсии. Все готово.

Немного сложно понять алгоритм, так как рекурсивный вызов идет до вывода разряда:

ten_base(in / base, base);
cout << int_symbol(in%base);

Это сделано для того, чтобы разряды выводились не от младшего к старшему, а наоборот, ведь в вывод они записываются слева направо. Если вы поменяете эти две строки местами, то будет слегка понятнее:

  1. Выводим младший разряд числа по какому-то основанию.
  2. Убираем младший разряд из числа (как будто убираем нижний кубик башенки) и повторяем процедуру.

Однако в таком случае разряды будут записаны в обратном порядке.

Не знаю, надеюсь, понятно объяснил.

UPD В самом начале я написал, что можно избежать дублирования. Будем запускать рекурсию лишь тогда, когда число не меньше основания:

void ten_base(int in, int base) {
    if (in >= base) {
        ten_base(in / base, base);
    }
    cout << int_symbol(in % base);
}

Таким образом, в данном коде больше нет дублирования cout << int_symbol(in % base), а принцип работы остается тем же.

READ ALSO
opencv пропускает секунду видео

opencv пропускает секунду видео

Есть видео: MPEG4 Video (H264) 960x540 30fps [V: h264 main L31, yuv420p, 960x540]

187
Почему вычитание быстрее сложения?

Почему вычитание быстрее сложения?

Написал несколько бенчмарков для вектора (использовал библиотеку гугла https://githubcom/google/benchmark) и получил странный результат: обход с циклом...

184
compareTo, как исправить ошибку

compareTo, как исправить ошибку

Здравствуйте, столкнулся с такой проблемой, что compareTo закидывает самую первую строчку из файла в конец после сортировкиТак выглядит код

211
Вопрос по ООП. Конкретный пример

Вопрос по ООП. Конкретный пример

Класс - реализация интерфейса, описывающего работникаУ каждого работника может быть менеджер, у каждого менеджера может быть менеджер итд

172