В прошлом году я писал программу для перевода из любой системы в любую систему счисления на си. Теперь потребовалось на Pascal.Функций стало больше. Некоторые пришлось просто копировать с других сайтов (да простят меня авторы)
К сожалению, точность вычислений здесь меньше, чем была на си — всего один знак после запятой точен.
Ограничение во FreePascal: числа в 16-ричной системе можно вводить только большими буквами. Нет функции UpperCase, писать было лень 🙂
Исходный код (FreePascal):
program test; uses crt, math, strings; var s, s1,s2 : string; // число для перевода base_in : integer; // Основание входной системы счисления base_out : integer; // Основание выходной системы счисления function CheckDotCount(s: string): boolean; // Проверка количества точек в числе var count, i : integer; begin count := 0; for i := 1 to Length(s) do if (s[i] = ‘.’) then inc(count); if (count > 1) then CheckDotCount := false else CheckDotCount := true; end; function IntToHex(ds: byte): string; const b: string = ‘0123456789ABCDEF’; begin if (b[(ds shr 4) + 1] = ‘0’) then IntToHex:= b[(ds and $F) + 1] else IntToHex:= b[(ds shr 4) + 1] + b[(ds and $F) + 1]; end; function HexToInt(s: string): Longword; var b: Byte; c: Char; r: Longword; begin r := 0; //s := UpperCase(s); for b := 1 to Length(s) do begin r := r * 16; c := s[b]; case c of ‘0’..’9′: Inc(r, Ord(c) — Ord(‘0’)); ‘A’..’F’: Inc(r, Ord(c) — Ord(‘A’) + 10); end; end; HexToInt := r; end; function checkSS(base : integer; s : string): boolean; var i: integer; flag : boolean; begin flag := true; for i := 1 to Length(s) do begin if (HexToInt(s[i]) >= base) then flag := false; end; if ((base > 16) or (base < 2)) then flag := false; checkSS := flag; end; function checkSSR (base : integer):boolean; begin if ((base >16) or (base < 2)) then checkSSR := false else checkSSR := true; end; function getStringBeforeDot(s:string): string; //pos : integer; begin if (Pos(‘.’,s) = 0) then getStringBeforeDot := s else getStringBeforeDot := Copy(s, 1,Pos(‘.’,s)-1); end; function getStringAfterDot(s: string):string; begin if (Pos(‘.’,s) = 0) then getStringAfterDot := » else getStringAfterDot := copy(s,Pos(‘.’,s)+1,Length(s)); end; procedure IntConverter(s:string; base_in : integer; base_out : integer); var n1,N,i,r1 : integer; d1 : array [0..255] of integer; begin n1 := Length(s); N := 0; for i := 1 to n1 do begin N:= N*base_in+HexToInt(s[i]); end; if (N = 0) then write (‘0’) else begin r1 := 0; while (N <>0) do begin d1[r1] := N mod base_out; N := N div base_out; inc(r1); end; for i:=r1-1 downto 0 do write(IntToHex(d1[i])); end; end; procedure DotConverter(s:string; base_in : integer; base_out : integer); var n2 , i, k2: longint; Nf : double; begin n2 := Length(s); if (n2 = 0) then begin writeln(); exit; end; write(‘.’); Nf := 0; for i := n2 downto 1 do begin Nf := (HexToInt(s[i]) + Nf) / base_in; end; k2 := 0; while ((Nf <> 0) AND (k2 < 5)) do begin inc(k2); write(IntToHex(floor(Nf*base_out))); Nf := ((Nf*base_out)); end; end; begin writeln(‘Введите число для перевода:’); readln(s); if (CheckDotCount(s) = false) then begin writeln(‘Во введеном числа более 1 точки, что-то не так’); exit; end; writeln(‘Введите основание входной системы счисления:’); readln(base_in); if (checkSS(base_in, s) = false) then begin writeln(‘Некорректная система счисления или число для этой системы счисления’); exit; end; writeln(‘Введите основание выходной системы счисления:’); readln(base_out); if (checkSSR(base_out) = false) then begin writeln(‘Некорректная система счисления или число для этой системы счисления’); exit; end; s1 := getStringBeforeDot(s); s2 := getStringAfterDot(s); IntConverter(s1,base_in,base_out); DotConverter(s2,base_in,base_out); readln; end.
На PascalABC нет некоторых функций, зато есть другие.
Урок 32. Перевод чисел между системами счисления
Пишем программу: перевод в разные системы счисления
Версия для PascalABC
program test; var s, s1,s2 : string; // число для перевода base_in : integer; // Основание входной системы счисления base_out : integer; // Основание выходной системы счисления function CheckDotCount(s: string): boolean; // Проверка количества точек в числе var count, i : integer; begin count := 0; for i := 1 to Length(s) do if (s[i] = ‘.’) then inc(count); if (count > 1) then CheckDotCount := false else CheckDotCount := true; end; function IntToHex(ds: byte): string; const b: string = ‘0123456789ABCDEF’; begin if (b[(ds shr 4) + 1] = ‘0’) then Result:= b[(ds and $F) + 1] else Result:= b[(ds shr 4) + 1] + b[(ds and $F) + 1]; end; function HexToInt(s: string): Longword; var b: Byte; c: Char; begin Result := 0; s := UpperCase(s); for b := 1 to Length(s) do begin Result := Result * 16; c := s[b]; case c of ‘0’..’9′: Inc(Result, Ord(c) — Ord(‘0’)); ‘A’..’F’: Inc(Result, Ord(c) — Ord(‘A’) + 10); end; end; end; function checkSS(base : integer; s : string): boolean; var i: integer; flag : boolean; begin flag := true; for i := 1 to Length(s) do begin if (HexToInt(s[i]) >= base) then flag := false; end; if ((base > 16) or (base < 2)) then flag := false; Result := flag; end; function checkSSR (base : integer):boolean; begin if ((base >16) or (base < 2)) then Result := false else Result := true; end; function getStringBeforeDot(s:string): string; //pos : integer; begin if (Pos(‘.’,s) = 0) then Result := s else Result := Copy(s, 1,Pos(‘.’,s)-1); end; function getStringAfterDot(s: string):string; begin if (Pos(‘.’,s) = 0) then Result := » else Result := copy(s,Pos(‘.’,s)+1,Length(s)); end; procedure IntConverter(s:string; base_in : integer; base_out : integer); var n1,N,i,r1 : integer; d1 : array [0..255] of integer; begin n1 := Length(s); N := 0; for i := 1 to n1 do begin N:= N*base_in+HexToInt(s[i]); end; if (N = 0) then write (‘0’) else begin r1 := 0; while (N <>0) do begin d1[r1] := N mod base_out; N := N div base_out; inc(r1); end; for i:=r1-1 downto 0 do write(IntToHex(d1[i])); end; end; procedure DotConverter(s:string; base_in : integer; base_out : integer); var n2 , i, k2: longint; Nf : double; begin n2 := Length(s); if (n2 = 0) then begin writeln(); exit; end; write(‘.’); Nf := 0; for i := n2 downto 1 do begin Nf := (HexToInt(s[i]) + Nf) / base_in; end; k2 := 0; while ((Nf <> 0) AND (k2 < 20)) do begin inc(k2); write(IntToHex(Floor(Nf*base_out))); Nf := ((Nf*base_out)); end; end; begin writeln(‘Введите число для перевода:’); readln(s); if (CheckDotCount(s) = false) then begin writeln(‘Во введеном числе более 1 точки, что-то не так’); exit; end; writeln(‘Введите основание входной системы счисления:’); readln(base_in); if (checkSS(base_in, s) = false) then begin writeln(‘Некорректная система счисления или число для этой системы счисления’); exit; end; writeln(‘Введите основание выходной системы счисления:’); readln(base_out); if (checkSSR(base_out) = false) then begin writeln(‘Некорректная система счисления или число для этой системы счисления’); exit; end; s1 := getStringBeforeDot(s); s2 := getStringAfterDot(s); IntConverter(s1,base_in,base_out); DotConverter(s2,base_in,base_out); readln; end.
Внимание, PascalABC и, соответственно, его версия исполняемых файлов требует .Net Framework Версии 4. Он встроен в Windows 8, но его нужно включить в компонентах Windows.
Версия запущенная в Pascal ABC
Источник: pyatnitsev.ru
Перевод десятичного числа в любую систему счисления
Написать программу, которая переводит десятичное число в любую другую систему счисления. Число и основание новой системы счисления вводятся с клавиатуры. При желании реализовать в программе функцию такого преобразования.
Решение задачи на языке программирования Python
Алгоритм перевода десятичного числа в любую другую систему счисления заключается в последовательном целочисленном делении сначала самого десятичного числа, а потом получаемых частных на основание системы счисления, в которую переводится число. Из остатков такого деления собирается представление числа в новой системе счисления. В той, на основание которой происходило деление. Сбор остатков происходит с конца.
Например, перевод десятичных чисел 160 в восьмеричную и 18 в двоичную системы счисления будет выглядеть так:
160 / 8 = 20 | 0 20 / 8 = 2 | 4 2 / 8 = 0 | 2
16010 = 2408
18 / 2 = 9 | 0 9 / 2 = 4 | 1 4 / 2 = 2 | 0 2 / 2 = 1 | 0 1 / 2 = 0 | 1
1810 = 100102
Даже если использовать этот алгоритм для перевода десятичного числа в десятичную систему счисления будет получен верный результат.
150 // 10 = 15 | 0 15 // 10 = 1 | 5 1 // 10 = 0 | 1
15010 = 15010
Проблема появляется в тот момент, когда основание системы счисления начинает превышать 10. В таких случаях нам не хватает привычных символов цифр (0-9) и требуется ввод дополнительных символов для обозначения значений, соответствующих десятичным числам 10, 11, 12 и т. д. Для примера переведем десятичное число в шестнадцатеричную систему счисления:
700 // 16 = 43 | 12 (C) 43 // 16 = 2 | 11 (B) 2 // 16 = 0 | 2
70010 = 2BC16
Десятичные остатки 12 и 11 при формировании шестнадцатеричного числа должны быть представлены одним разрядом. В таких случаях в качестве цифр, чье значение больше 9-ти, используются английские буквы. Так числу 10 будет соответствовать символ A , числу 11 — B и т. д.
Таким образом, при написании программы перевода десятичного числа в любую систему счисления мы должны предусмотреть подмену остатков на соответствующие им символы, если эта замена требуется.
Будем усложнять программу поэтапно и сначала напишем вариант кода, который переводит не в любую систему счисления, а только с основанием до 10-ти.
num = int(input()) base = 0 while not (2 base 9): base = int(input(«Основание (2-9): «)) new = » while num > 0: remainder = num % base new = str(remainder) + new num = num // base print(new)
В цикле сначала вычисляется остаток. Далее присоединям его спереди к строковой переменной new , в которой хранится представление числа в новой системе счисления. Последним действием присваиваем переменной num частное от целочисленного деления прежнего значения num на основание системы счисления.
Поскольку в языке программирования Python есть функция divmod , сократим код, объединив нахождение остатка и целочисленное деление:
. while num > 0: num, remainder = divmod(num, base) new = str(remainder) + new .
Вызов divmod(num, base) возвращает кортеж из частного и остатка от деления num на base . Далее частное присваивается num , остаток — remainder .
Теперь напишем программу, которая переводит число исключительно в шестнадцатеричную систему счисления. Для хранения символов, которыми будут заменяться двузначные остатки, используем строку из этих символов.
num = int(input()) base = 16 letters = ‘ABCDEF’ new = » while num > 0: num, remainder = divmod(num, base) if remainder > 9: letter_id = remainder — 10 remainder = letters[letter_id] new = str(remainder) + new print(new)
Числу 10 соответствует символ A . Поэтому если остаток равен десяти, то letter_id будет равно нулю. Символ под индексом 0 в строке букв — как раз A . Если остаток равен 15-ти, то letter_id будет равно пяти, а letters[5] вернет F .
Программу можно упростить, если в строку символов добавить цифры. В этом случае остатки будут точно соответствовать индексам, под которыми находятся соответствующие им символы.
num = int(input()) base = 16 letters = ‘0123456789ABCDEF’ new = » while num > 0: num, remainder = divmod(num, base) new = letters[remainder] + new print(new)
На этом этапе должно стать понятно, как написать программу конвертации десятичного числа в почти любую систему счисления. Достаточно немного подправить код перевода в шестнадцатеричную систему, дописав в строку дополнительный набор символов, а не заканчивать ее на F .
Чтобы не хранить в программе строку большой длины и избежать ошибки из-за нечаянно пропущенного какого-нибудь символа, вернемся к варианту, в котором остатки больше девяти заменяются в теле условного оператора. При этом буквы будем брать не из определенной в коде строки, а из встроенной таблицы символов.
num = int(input()) base = 0 while not (2 base 36): base = int(input(«Основание (2-36): «)) new = » while num > 0: num, remainder = divmod(num, base) if remainder > 9: letter = remainder — 10 remainder = chr(ord(‘A’) + letter) new = str(remainder) + new print(new)
Вызов ord(‘A’) возвращает код буквы A в таблице Unicode. К этому коду-числу мы прибавляем смещение по алфавиту (значение letter ). С помощью функции chr() получаем соответстующую коду букву.
def convert_integer(decimal, radix): if radix > 36: return «Основание системы счисления должно быть не больше 36-ти» number = » while decimal > 0: decimal, remainder = divmod(decimal, radix) if remainder > 9: remainder = chr(ord(‘A’) + remainder — 10) number = str(remainder) + number return number num = int(input(«Десятичное число: «)) base = int(input(«Основание (2-36): «)) print(convert_integer(num, base))
Ограничение по основанию в 36 связано с количеством букв в английском алфавите. Их 26, плюс десять цифр. Расширить диапазон оснований можно за счет взятия недостающих символов из какой-либо другой части таблицы Unicode. Например, можно добавить к условному оператору ветку elif с условием remainder > 35 , а в теле вычитать из remainder 36.
Однако написать программу, которая переводит десятичное число в абсолютно любую систему счисления нельзя. Иначе надо суметь решить задачу генерации случайного символа, который не должен быть похож ни на какой из полученных ранее.
X Скрыть Наверх
Решение задач на Python
Источник: younglinux.info
Перевод из любой системы счисления в любую чисел большой длины
Недавно решал задачи по криптографии, и возникла необходимость переводить очень большие числа из одной системы счисления в другую. С двоичной, восьмеричной, десятичной и шестнадцатеричной системой справляется и стандартный калькулятор ОС. Но он не рассчитан на числа большой длины. А мне как раз необходимо работать с числами длиной >1000 знаков.
Для этих целей решил написать небольшой консольный конвертер, позволяющий работать с числами любой длины и любой системы счисления от 2 до 36.
Требования:
• Конвертер должен работать с числами любой длины.
• Конвертер должен работать в любой системе счисления от 2 до 36.
• Конвертер должен уметь работать с файлами.
Реализация:
Писать решил на языке C++. Люблю этот язык, да и перевести исходники в другой язык из C++ не составляет особого труда.
Написал следующий класс:
class Converter < private: //Вектор содержит исходное число vectora; //Исходная система счисления 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 iriginal )< return c — ‘0’; >else< if ( c >= ‘A’ c iriginal )< return c — ‘A’ + 10; >else < return -1; >> > //Переводит число в символ char intToChar(int c)< if ( c >= 0 c else < return c + ‘A’ — 10; >> //Получает следующую цифру числа в новой системе счисления int nextNumber(int final)< int temp = 0; for ( int i = 0; ia.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; ia.size(); i++ ) < if ( a[i] != 0 )< return false; >> return true; > //Конвертирует исходное число в заданную систему счисления string convertTo(int final) < vectorb; 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 fin.close(); Converter conv(origNumber,original); //Если не был задан файл для вывода, то результат отобразиться на экране if ( argc > 4 )< //Адрес файла для записи нового числа string outputFile = argv[4]; ofstream fout(outputFile.c_str()); if ( fout.is_open() )< fout else < cout >else
Код, конечно, далек от идеала, но зато все просто и понятно.
Теперь можно протестировать.
Конвертер готов, теперь осталось его испытать. Создаю файл, содержащий число, представляющее из себя тысячу девяток.
Запускаю в консоли:
Конвертер удачно создает файл output.txt, содержащий число, длиной 3322 символа.
Теперь выведу его на экран, для этого достаточно не задавать файл для вывода.
Так же можно задавать исходное число прямо в консоли
Вывод:
Если нужно конвертировать что-то очень большое, то данный конвертер отлично для этого подойдет. Отсутствие интерфейса позволяет без изменения запускать написанный код на любой платформе. А консоль забывать нельзя, будь то windows или Linux…
Скачать проект(VS 2008) можно здесь.
Источник: habr.com