function ConvertFromNumber(aBase, aNumber : integer): string;
const CDigits : string = '0123456789ABCDEF';
var n : integer; c : char; S : string;
begin
S:=''; { Накопитель цифр }
repeat
n:= aNumber mod aBase; { остаток от деления на основание }
aNumber:= aNumber div aBase; { частное от деления на основание }
c:= CDigits[1+n]; { выбираем цифру из строки }
S:= c + S; { вставляем цифру в результат }
until aNumber=0;
ConvertFromNumber:= S; { готово! }
end;
var B, N : integer; { B – основание системы, N – число }
begin {=== Главная программа ===}
repeat
Write('Основание системы= '); Readln(B);
if B in [2..16] then begin
Write('Преобразуемое число= '); Readln(N);
Writeln(ConvertFromNumber(B, N));
end
until not (B in [2..16]);
end.
Эта простая программа подарит вам счастье наблюдать знакомые десятичные числа в экзотических системах счисления, например, в троичной или пятеричной.
Обратное преобразование
Теперь займемся обратной задачей: пусть дана строка символов, изображающая некое число в известной системе счисления; требуется преобразовать эту строку в число и напечатать в десятичной системе.
Сборка числа из десятичных цифр нами освоена. Она выполнялась умножением накопленной суммы на десять с прибавлением очередной цифры, начиная со старшей. Надо ли объяснять, что сборка в других системах выполняется точно так же? Только умножать будем не на десять, а на основание системы счисления. В следующей ниже программе сборка выполняется функцией ConvertToNumber – «преобразовать в число».
{ P_47_2 – Преобразование из других систем счисления }
function ConvertToNumber(aBase: integer; aNumber: string): integer;
var i,n, Sum : integer;
c : char;
begin
Sum:=0; { Накопитель результата }
for i:=1 to Length(aNumber) do begin
c:= Upcase(aNumber[i]);
if c in ['0'..'9']
then n:= Ord(c)-Ord('0') {0..9}
else n:= 10+Ord(c)-Ord('A'); {10..15}
Sum:= aBase*Sum + n; { Накопление суммы }
end;
ConvertToNumber:= Sum; { готово! }
end;
var B : integer; { Основание системы }
N : string; { Изображение числа в виде строки }
begin {=== Главная программа ===}
repeat
Write('Основание системы= '); Readln(B);
if B in [2..16] then begin
Write('Преобразуемое число= '); Readln(N);
Writeln(ConvertToNumber(B, N));
end
until not (B in [2..16]);
end.
Как обычно, здесь выделены операторы, стоящие внимания. Функция UpCase преобразует строчные латинские буквы в заглавные. Ведь шестнадцатеричные цифры от «A» до «F» могут быть введены пользователем в любом регистре, а последующие операторы преобразования цифры в число предполагают заглавные буквы – вот потому и понадобилась функция UpCase.
Теперь о превращении символов в числа. Цифры от «0» до «9» преобразуются вычитанием из кода цифры кода символа «0». Для цифр от «A» до «F» после вычитания кода буквы «A» к разности прибавляем число 10. Все сказанное относится к следующему условному оператору.
if c in ['0'..'9']
then n:= Ord(c)- Ord('0') {0..9}
else n:= 10 + Ord(c)- Ord('A'); {10..15}
Вот, пожалуй, и вся премудрость. Испытание этой программы убедит вас в том, что волшебства случаются не только в сказках!
Итоги
• Способ изображения чисел посредством знаков называется системой счисления.
• Одно и то же число может быть изображено в разных системах счисления.
• Все современные системы счисления – позиционные. Это значит, что вес цифры определяется позицией в числе.
• Преобразование числа в любую систему счисления (строку цифр) начинается с младших разрядов, а обратная сборка – со старших.
А слабо?
А) Напишите функцию для преобразования числа из одной системы счисления в другую. Функция должна принимать три параметра:
• строку в исходной системе счисления;
• основание исходной системы;
• основание конечной системы счисления.
Воспользуйтесь вызовами готовых функций ConvertToNumber и ConvertFromNumber.
Б) У программиста Ника была привычка запоминать сумму цифр в номерах автомобилей, попадавшихся ему на глаза. Однажды он стал свидетелем аварии, виновник которой скрылся. Ник сообщил полицейским только сумму цифр в номере нарушителя (сам номер Ник не помнил). Помогите полиции, и напишите программу, выводящую все трехзначные номера (от 001 до 999), сумма цифр которых равна N (значение N вводит пользователь).
В) Напишите функцию для представления чисел словами. Например, число 45 должно быть преобразовано в строку «сорок пять». Решайте задачу постепенно: сначала для однозначных и двузначных чисел, затем для более крупных. Или слабо?
Г) В романе «Евгений Онегин» есть такие строки: «Все предрассудки истребя, мы почитаем всех нулями, а единицами – себя». О какой системе счисления упомянул Александр Сергеевич?
Д) В функцию передаются три параметра: 1) число, 2) основание системы счисления, 3) символ цифры. Функция должна возвратить количество вхождений этой цифры в представление числа для указанной системы счисления.
Е) Напечатать все трехзначные числа, цифры которых (в десятичном представлении) различны, например: 123, 702.
Ж) Найти все шестизначные счастливые билеты. Счастливыми называют билеты, у которых сумма первых 3-х цифр равна сумме следующих 3-х. Например: 123 411. Напишите булеву функцию, определяющую «счастливость» билета.
З) В заморской стране обращались денежные купюры достоинством в 1, 2, 5, 10 и 25 пиастров. Напишите программу для кассового аппарата, определяющую наименьший набор купюр, необходимый для выдачи сдачи на указанную сумму. Например, для сдачи 33 пиастров программа напечатает: 25 + 5 + 2 + 1.
И) Программа шифрования текстового файла заменяет каждый символ двумя шестнадцатеричными цифрами его кода. Например, три символа ‘405’ заменяются на шесть символов ‘343035’. Символы разбивки строк не затрагиваются. Напишите программу для зашифровки и расшифровки файла по этой системе.
К) Чтобы усилить шифр предыдущей задачи, выполните вращение преобразованной строки на несколько позиций: влево – при зашифровке, и вправо – при расшифровке (смотрите задачи к главе 44).
Л) Напечатайте все числа, не превышающие 1000, такие, что делятся без остатка на каждую из своих цифр. Например: 24, 36, 184, 612. Определите количество таких чисел.
Глава 48
Железная логика
Разбираясь с двоичной системой, мы заглянули внутрь компьютера и обнаружили там регистры, что хранят и обрабатывают числа.
Два взгляда на компьютерные «кирпичики»
Регистры построены из триггеров – элементарных ячеек памяти, способных хранить один бит информации. В регистре может быть 8, 16, 32 или 64 триггера, что соответствует 1, 2, 4 или 8 байтам. Так видят устройство компьютера инженеры-электроники.
А программисты? Они видят то же самое, только называют иначе (рис. 108). То, что электроники именуют триггерами, программисты называют битами, а регистры нам видны как байты, слова и т.д. Так, в Паскале 8-битовый регистр соответствует типу Byte, 16-битовый – типу Word, а 32-битовый – типу Longint.