Недавно решал задачи по криптографии, и возникла необходимость переводить очень большие числа из одной системы счисления в другую. С двоичной, восьмеричной, десятичной и шестнадцатеричной системой справляется и стандартный калькулятор ОС. Но он не рассчитан на числа большой длины. А мне как раз необходимо работать с числами длиной >1000 знаков.Для этих целей решил написать небольшой консольный конвертер, позволяющий работать с числами любой длины и любой системы счисления от 2 до 36.
Требования:
• Конвертер должен работать с числами любой длины.
• Конвертер должен работать в любой системе счисления от 2 до 36.
• Конвертер должен уметь работать с файлами.
Реализация:
Писать решил на языке C++. Люблю этот язык, да и перевести исходники в другой язык из C++ не составляет особого труда.
Написал следующий класс:
class Converter{ private: //Вектор содержит исходное число vector<int> a; //Исходная система счисления int iriginal; public: //Конструктор, содержит 2 параметра: строка исходного числа, исходная система счисления Converter(string str, int original){ this->iriginal = original; //Заносит числа исходного числа в вектор for ( int i=0; i < str.length(); i++ ){ this->a.push_back(charToInt(str[i])); } } //Переводит символ в число, вместо некорректных символов возвращает -1 int charToInt(char c){ if ( c >= '0' && c <= '9' && (c - '0') < this->iriginal ){ return c - '0'; }else{ if ( c >= 'A' && c <= 'Z' && (c - 'A') < this->iriginal ){ return c - 'A' + 10; }else { return -1; } } } //Переводит число в символ char intToChar(int c){ if ( c >= 0 && c <= 9 ){ return c + '0'; }else{ return c + 'A' - 10; } } //Получает следующую цифру числа в новой системе счисления int nextNumber(int final){ int temp = 0; for ( int i = 0; i<this->a.size(); i++){ temp = temp*this->iriginal + this->a[i]; a[i] = temp / final; temp = temp % final; } return temp; } //Возвращает true - если массив состоит из одних нулей и false в противном случае bool zero(){ for ( int i=0; i<this->a.size(); i++ ){ if ( a[i] != 0 ){ return false; } } return true; } //Конвертирует исходное число в заданную систему счисления string convertTo(int final){ vector<int> b; int size = 0; do { b.push_back(this->nextNumber(final)); size++; }while( !this->zero() ); string sTemp=""; for (int i=b.size()-1; i>=0; i--){ sTemp += intToChar(b[i]); } return sTemp; } };
Код получился достаточно простой
Далее прикрутил его в проект:
//Адрес файла, содержащего исходное число string inputFile = argv[1]; //Исходная система счисления int original = atol(argv[2]); //Требуемая система счисления int final = atol(argv[3]); //Строка, содержащая исходное число string origNumber; ifstream fin(inputFile.c_str()); if ( fin.is_open() ){ fin >> origNumber; }else{ cout << "File " << inputFile << " not open" << endl; //Небольшой костыль - если неудалось открытьфайл, возможно вместо его ввели требуемое число origNumber = inputFile; } fin.close(); Converter conv(origNumber,original); //Если не был задан файл для вывода, то результат отобразиться на экране if ( argc > 4 ){ //Адрес файла для записи нового числа string outputFile = argv[4]; ofstream fout(outputFile.c_str()); if ( fout.is_open() ){ fout << conv.convertTo(final); }else{ cout << "File " << outputFile << " not create" << endl; cout << conv.convertTo(final) << endl; } }else{ cout << conv.convertTo(final) << endl; }
Код, конечно, далек от идеала, но зато все просто и понятно.
Теперь можно протестировать.
Конвертер готов, теперь осталось его испытать. Создаю файл, содержащий число, представляющее из себя тысячу девяток.
Запускаю в консоли:

Конвертер удачно создает файл output.txt, содержащий число, длиной 3322 символа.
Теперь выведу его на экран, для этого достаточно не задавать файл для вывода.

Так же можно задавать исходное число прямо в консоли

Вывод:
Если нужно конвертировать что-то очень большое, то данный конвертер отлично для этого подойдет. Отсутствие интерфейса позволяет без изменения запускать написанный код на любой платформе. А консоль забывать нельзя, будь то windows или Linux…
Скачать проект(VS 2008) можно здесь.
