Как определить новую систему счисления в C ++

По сути, я пытаюсь создать базовую систему счисления 62 в C ++ (буквенно-цифровая система счисления - та, которая включает в себя a-z, A-Z и 0-9). Как бы что-то подобное произошло? Я попытался использовать массив символов следующим образом:

const char alphaNum[62] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', ' y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };

однако написание функций для использования этого массива и попытки подсчета требует слишком много кода, чтобы быть практичным (для 0–61, конечно, просто выберите его из массива. Проблема возникает, когда вы пытаетесь сделать многозначные числа, т.е. 00). Было бы намного проще просто сказать foobar++;. У кого-нибудь есть способ определить системы счисления или, по крайней мере, для меня, чтобы я сделал так, чтобы мне не приходилось писать кейс для каждого случая, когда он достигает Z?

РЕДАКТИРОВАТЬ: это должен был быть const char, не знаю, почему VS решил, что было бы забавно не копировать некоторые из них.

4 голоса | спросил Antonio Escalera 15 J0000006Europe/Moscow 2014, 00:48:05

3 ответа


0

Может помочь следующее: ( http://ideone.com/y1gZDF ) (Вы можете изменить внутреннее представление так, как вам нужно, как BigNumber ).

class N62
{
public:
    explicit N62(const std::string& digits) : N62(digits.c_str(), digits.size()) {}
    N62(const char* digits, std::size_t len) : value(0u)
    {
        for (std::size_t i = 0; i != len; ++i) {
            auto pos = std::find(std::begin(base), std::end(base), digits[i]);
            if (pos == std::end(base)) {
                throw std::runtime_error("incorrect digit");
            }
            value *= 62;
            value += pos - std::begin(base);
        }
    }
    N62(std::size_t value) : value(value) {}
    operator std::size_t () const { return value; }
    std::string str() const
    {
        if (value == 0u) {
            return "0";
        }
        std::string res;
        for (std::size_t n = value; n != 0; n /= 62) {
            res.push_back(base[n % 62]);
        }
        std::reverse(res.begin(), res.end());
        return res;
    }

private:
    std::size_t value;
private:
    static constexpr char base[] =
        "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
};

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

N62 operator "" _n62 (const char *t, std::size_t len)
{
    return N62(t, len);
}

И используйте это следующим образом: "1Z"_n62 (которые разрешаются в 123 в десятичном виде). ​​

ответил Jarod42 15 J0000006Europe/Moscow 2014, 01:53:31
0

Вам необходимо разделить внешнее (для пользователя) представление и внутреннее представление.

Внутреннее представительство
Внутри компьютера вы должны использовать наиболее эффективное представление. Это может быть шестнадцатеричное, двоичное или десятичное число; или не беспокойся об этом.

При представлении Пользователю вы должны использовать Внешнее Представление.

Внешнее представительство
Ваш массив символов представляет цифры вашей системы счисления. (Это также должно быть const.) Вам необходимо изолировать цифры от вашего внутреннего представления. Например, в базе 16 мы делим число на 16, чтобы сместить число вправо, и используем деление modulo , чтобы получить остаток. Остальная часть - это цифра. Используйте остаток, чтобы найти представление цифр из вашего массива.

Попробуйте свои алгоритмы на меньшей числовой основе, такой как 17 или 18. Расширение до базы 62 должно быть вопросом изменения #define или const integer.

Изменить 1: сложный метод
Более сложный метод - использовать один байт для каждой цифры вашей системы счисления. Байт, октет или беззнаковый символ имеет диапазон от 0 до 255, поэтому должен содержать цифру от основания 62.

Используйте std::vector<unsigned char> для представления своего номера. Вам нужно решить, находится ли самая значимая цифра в начале вектора или в конце.

Чтобы увеличить цифру:

  add 1 to digit.
  if digit value > 62
  {
     set digit to zero.
     Load digit with next greater column value (i.e. vector[position + 1];
     Repeat at top of algorithm
  }

Это стандартный алгоритм независимо от базы (10, 8, 16 и т. д.).
Основные правила десятичного сложения, вычитания, умножения и деления все еще применяются. (Подсказка).

Этот метод используется в библиотеках Big Number .

ответил Thomas Matthews 15 J0000006Europe/Moscow 2014, 00:56:17
0

Системы счисления являются только представлениями чисел. Числа не против того, как мы их пишем. Итак, наши проблемы:

Как использовать base62 для объявления чисел в тексте программы?

Вы должны указать, как вы помечаете номера base62. Префикс «0x» и «$» зарезервирован для base16, префикс «0» зарезервирован в восьмеричном формате, префикс «%» для двоичного файла, «*» используется по нескольким причинам, возможно, тильда - это ваш префикс, пример: ~ Uu3n

Затем вы должны написать препроцессор, который преобразует ваши числа base62 в десятичный (или шестнадцатеричный, как вы хотите) формат.

Как вывести числа в base62?

Это сложнее. Вы должны преобразовать все выходные данные в base62. Так

 printf("%d in base62 is %D \n",value,value);

должен быть преобразован в

 printf("%d in base62 is %s \n",value,tob64(value));

Не слишком элегантно.


Может быть, класс-оболочка должен быть лучше (например, Integer в Java).

ответил ern0 15 J0000006Europe/Moscow 2014, 01:09:35

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132