Pull to refresh

Перевод из любой системы счисления в любую чисел большой длины

Reading time 3 min
Views 32K
Двоичные часыНедавно решал задачи по криптографии, и возникла необходимость переводить очень большие числа из одной системы счисления в другую. С двоичной, восьмеричной, десятичной и шестнадцатеричной системой справляется и стандартный калькулятор ОС. Но он не рассчитан на числа большой длины. А мне как раз необходимо работать с числами длиной >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 символа.
Теперь выведу его на экран, для этого достаточно не задавать файл для вывода.
Вывод результата на экран
Так же можно задавать исходное число прямо в консоли
Вывод результата на экран 2

Вывод:

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

Articles