1. Определение кода числа системы счисления
Сначала создадим вспомогательную функцию SystemNumChar , необходимая для
нашей работы. Она конвертирует цифру в букву латинского алфавита. Например, цифра
'11' – это 'B';
'15' – это F';
'7' – это '7'
(цифры от 0 до 9 остаются без изменений).
function SystemNumChar(n: byte): char;
begin
Result:='0';
if n<=9 then
Result:=Char(48+n);
if (n>=10) and (n<=35) then
Result:=Char(55+n);
end;
где:
Например,
SystemNumChar(2) выведет
'2';
SystemNumChar(14) выведет
'E' (как в шестнадцатеричной системе счисления);
SystemNumChar(33) выведет
'X'.
Примечание. В настоящее время существуют 16-ричные
системы счисления, однако автор решил пофантазировать и расширил весь латинский
алфавит. Поэтому не стоит удивляться, если при вызове функции
SystemNumChar(35) выведет
'Z'. Но может в дальнейшем "изобретут" 32-ричные
системы счисления, 36-ричные и т.д.
Также создадим вспомогательную функцию SystemNumByte , обратная
функции SystemNumChar .
function SystemNumByte(c: char): byte;
begin
Result:=0;
c:=UpCase(c);
if (c>='0') and (c<='9') then
Result:=Ord(c)-48;
if (c>='A') and (c<='Z') then
Result:=Ord(c)-55;
end;
где:
c – буква от 0 до 9, от A до Z.
Например,
SystemNumByte('7') выведет
'7';
SystemNumByte('F') выведет
'15';
SystemNumByte('z') выведет
'35' (не зависит от регистра букв).
Перевод целых положительных чисел из одной системы счисления в другую
2. Перевод чисел из десятичной системы счисления в двоичную (частный случай)
1 вариант:
function SystemNum10to2(n: int64): string;
var i: byte;
begin
Result:='';
while n>0 do
begin
i:=n mod 2;
Result:=IntToStr(i)+Result;
n:=n div 2;
end;
if Result='' then
Result:='0';
end;
2 вариант:
function SystemNum10to2(n: int64): string;
var i: byte;
begin
Result:='';
while n>0 do
begin
i:=n and 1;
Result:=IntToStr(i)+Result;
n:=n shr 1;
end;
if Result='' then
Result:='0';
end;
где:
n – исходное десятичное число.
Например,
SystemNum10to2(12) выведет
'1100';
SystemNum10to2(45) выведет
'101101'.
3. Перевод чисел из десятичной системы счисления в шестнадцатеричную (частный случай)
function SystemNum10to16(n: int64): string;
var i: byte;
begin
Result:='';
while n>0 do
begin
i:=n mod 16;
Result:=SystemNumChar(i)+Result;
n:=n div 16;
end;
if Result='' then
Result:='0';
end;
где:
n – исходное десятичное число.
Например,
SystemNum10to16(24) выведет
'18';
SystemNum10to16(16383) выведет
'3FFF'.
4. Перевод чисел из десятичной системы счисления в любую другую
function SystemNum10toB(n: int64; b: byte): string;
var i: byte;
begin
Result:='';
if (b<2) or (b>36) then
Exit;
while n>0 do
begin
i:=n mod b;
Result:=SystemNumChar(i)+Result;
n:=n div b;
end;
if Result='' then
Result:='0';
end;
где:
n – исходное десятичное число;
b – система счисления.
Например,
SystemNum10toB(225, 2) выведет
'11100001';
SystemNum10toB(173, 5) выведет
'1143';
SystemNum10toB(541, 16) выведет
'21D';
- самое интересное, что
SystemNum10toB(1583, 36)
выведет '17Z'.
5. Перевод чисел из двоичной системы счисления в десятичную (частный случай)
function SystemNum2to10(s: string): int64;
var i, k: byte;
step: int64;
begin
Result:=0;
step:=1;
for i:=Length(s) downto 1 do
begin
if (s[i]<'0') or (s[i]>'1') then
begin
{ защита от посторонних символов }
Result:=0;
Exit;
end;
k:=StrToInt(s[i]);
Result:=Result+k*step;
step:=step*2;
end;
end;
где:
s – исходное двоичное число.
Например,
SystemNum2to10('1110') выведет
'14'.
6. Перевод чисел из шестнадцатеричной системы счисления в десятичную (частный случай)
function SystemNum16to10(s: string): int64;
var i, k: byte;
step: int64;
begin
Result:=0;
step:=1;
for i:=Length(s) downto 1 do
begin
k:=SystemNumByte(s[i]);
Result:=Result+k*step;
step:=step*16;
end;
end;
где:
s – исходное шестнадцатеричное число.
Например,
SystemNum16to10('E40A') выведет
'58378'.
7. Перевод чисел из любой системы счисления в десятичную
function SystemNumAto10(s: string; a: byte): int64;
var i, k: byte;
step: int64;
begin
Result:=0;
if (a<2) or (a>36) then
Exit;
step:=1;
for i:=Length(s) downto 1 do
begin
k:=SystemNumByte(s[i]);
Result:=Result+k*step;
step:=step*a;
end;
end;
где:
s – исходное число любой системы счисления, записанное в
строковом виде;
a – система счисления.
Например,
SystemNumAto10('11001', 2) выведет
'25';
SystemNumAto10('8137', 9) выведет
'5947';
SystemNumAto10('6a7D', 16) выведет
'27261' (не зависит от регистра букв);
SystemNumAto10('53z', 36) выведет
'6623'.
8. Перевод чисел из двоичной системы счисления в шестнадцатеричную (частный случай)
function SystemNum2to16(s: string): string;
const Base: array[0..15, 0..1] of string =
(('0000', '0'), ('0001', '1'), ('0010', '2'), ('0011', '3'),
('0100', '4'), ('0101', '5'), ('0110', '6'), ('0111', '7'),
('1000', '8'), ('1001', '9'), ('1010', 'A'), ('1011', 'B'),
('1100', 'C'), ('1101', 'D'), ('1110', 'E'), ('1111', 'F'));
var i, j: byte;
begin
Result:='';
while Length(s) mod 4<>0 do
s:='0'+s;
for i:=1 to Length(s) div 4 do
for j:=Low(Base) to High(Base) do
if Base[j, 0]=Copy(s, 4*i-3, 4) then
begin
Result:=Result+Base[j, 1];
Break;
end;
if Result='' then
Result:='0';
end;
где:
s – исходное двоичное число.
Например,
SystemNum2to16('101101') выведет
'2D';
SystemNum2to16('111000110') выведет
'1C6'.
9. Перевод чисел из шестнадцатеричной системы счисления в двоичную (частный случай)
function SystemNum16to2(s: string): string;
const Base: array[0..15, 0..1] of string =
(('0000', '0'), ('0001', '1'), ('0010', '2'), ('0011', '3'),
('0100', '4'), ('0101', '5'), ('0110', '6'), ('0111', '7'),
('1000', '8'), ('1001', '9'), ('1010', 'A'), ('1011', 'B'),
('1100', 'C'), ('1101', 'D'), ('1110', 'E'), ('1111', 'F'));
var i, j: byte;
begin
Result:='';
for i:=1 to Length(s) do
for j:=Low(Base) to High(Base) do
if Base[j, 1]=UpCase(s[i]) then
begin
Result:=Result+Base[j, 0];
Break;
end;
while (Result<>'') and (Result[1]='0') do
Delete(Result, 1, 1);
if Result='' then
Result:='0';
end;
где:
s – исходное шестнадцатеричное число.
Например,
SystemNum16to2('3a') выведет
'111010'.
10. Перевод чисел из любой системы счисления в любую другую (общий случай)
1 вариант:
function SystemNumAtoB(s: string; a, b: byte): string;
var i, k: byte;
n, step: int64;
begin
Result:='';
if (a<2) or (a>36) or (b<2) or (b>36) then
Exit;
{ перевод в десятичное число }
n:=0;
step:=1;
for i:=Length(s) downto 1 do
begin
k:=SystemNumByte(s[i]);
n:=n+k*step;
step:=step*a;
end;
{ далее перевод в нужную систему счисления }
while n>0 do
begin
i:=n mod b;
Result:=SystemNumChar(i)+Result;
n:=n div b;
end;
if Result='' then
Result:='0';
end;
2 вариант:
function SystemNumAtoB(s: string; a, b: byte): string;
var n: int64;
begin
n:=SystemNumAto10(s, a);
Result:=SystemNum10toB(n, b);
end;
где:
s – исходное число любой системы счисления, записанное в
строковом виде;
a – система счисления числа s ;
b – система счисления получаемого числа.
Например,
SystemNumAtoB('11110', 2, 10) выведет
'30';
SystemNumAtoB('2B', 16, 10) выведет
'43';
SystemNumAtoB('114', 8, 16) выведет
'4C';
SystemNumAtoB('z', 36, 2) выведет
'100011';
SystemNumAtoB('B93', 12, 25) выведет
'2HK'.
Перевод вещественных положительных чисел из одной системы счисления в другую
Под вещественными числами в программировании понимаются дробные десятичные числа.
11. Перевод вещественных чисел из десятичной системы счисления в любую другую
function SystemNumR10toB(n: real; b, c: byte): string;
var i: byte;
begin
Result:=SystemNum10toB(Trunc(n), b);
if c>0 then
Result:=Result+',';
for i:=1 to c do
begin
n:=Frac(n)*b;
Result:=Result+SystemNumChar(Trunc(n));
end;
end;
где:
n – исходное вещественное десятичное число;
b – система счисления;
c – количество цифр после запятой.
Например,
SystemNumR10toB(9.875, 2, 5) выведет
'1001,11100';
SystemNumR10toB(25.93, 6, 10) выведет
'41,5325140251';
SystemNumR10toB(0.01, 16, 7) выведет
'0,028F5C2'.
12. Перевод вещественных чисел из любой системы счисления в десятичную
function SystemNumRAto10(s: string; a: byte): real;
var i, k: byte;
step: int64;
sk { дробная часть числа }: string;
begin
Result:=0;
if (a<2) or (a>36) then
Exit;
k:=Pos(',', s);
if k>0 then
begin
sk:=Copy(s, k+1, Length(s));
s:=Copy(s, 1, k-1);
end else
sk:='';
Result:=SystemNumAto10(s, a);
step:=a;
for i:=1 to Length(sk) do
begin
k:=SystemNumByte(sk[i]);
Result:=Result+k/step;
step:=step*a;
end;
end;
где:
s – исходное вещественное число любой системы счисления,
записанное в строковом виде;
a – система счисления.
Например,
SystemNumRAto10('11,0001', 2) выведет
'3,0625';
SystemNumRAto10('62,017', 7) выведет
'44,0408163265306';
SystemNumRAto10('A,3D', 16) выведет
'10,23828125'.
Перевод целых отрицательных чисел из одной системы счисления в другую
Существуют ограничения на числа, которые могут быть записаны в n-разрядную
ячейку памяти. При знаковом представлении целых чисел старший разряд ячейки
отводится под знак (0 – для положительных, 1 – для отрицательных чисел),
а остальные разряды – под цифры числа. Возьмем, например, число
'147', двоичная запись которого –
'10010011'. Также возьмем число
'-109', двоичная запись которого –
'10010011'. Мы видим, что двоичные коды чисел
'147' и '-109'
совпадают. Если для числа '147' потребуется 2 байта
памяти (16-разрядная ячейка памяти), то для числа
'-109' хватит 1 байта (8-разрядная ячейка).
Поэтому при переводе отрицательных чисел нужно указывать количество разрядов.
Следовательно, вышеуказанные функции для перевода отрицательных чисел точно не
подойдут!
13. Перевод отрицательных чисел из десятичной системы счисления в любую другую
function SystemNumN10toB(n: int64; b: byte): string;
var i, k, z, len: byte;
min, max: int64;
minus: boolean;
procedure BitCount(byt { байты }: byte);
var a, b: int64;
bit { биты }: byte;
begin
bit:=8*byt-1;
a:=-(int64(1) shl bit); // -128
b:=int64(1) shl bit - 1; // 127
if (a<=n) and (n<=b) then
begin
min:=a;
max:=b;
z:=byt; // 1 (байт)
end;
end;
begin
Result:='';
if (b<2) or (b>36) then
Exit;
{ определяем диапазон допустимых чисел, например, от -128 до 127 (1 байт) }
min:=0;
max:=0;
z:=0;
BitCount(8);
BitCount(4);
BitCount(2);
BitCount(1);
{ определяем длину выводимой строки результата }
case b of
2: len:=8*z;
3: len:=5*z;
4..6: len:=4*z;
7..15: len:=3*z;
else
len:=2*z;
end;
{ процесс вычисления }
minus:=n<0;
n:=Abs(n);
z:=1;
for k:=1 to len do
begin
i:=n mod b;
if minus then
begin
i:=b-i+z-1;
z:=i div b;
i:=i mod b;
end;
Result:=SystemNumChar(i)+Result;
n:=n div b;
end;
end;
где:
n – исходное десятичное число;
b – система счисления.
Например,
SystemNumN10toB(-128, 2) выведет
'10000000';
SystemNumN10toB(-255, 6) выведет
'55554453';
SystemNumN10toB(-1024, 16) выведет
'FC00';
SystemNumN10toB(1024, 16) выведет
'0400'.
Примечание. В этой функции предусмотрена
автоматическая длина выводимого результата. Если производить вычисления на
стандартном калькуляторе (в любой операционной системе есть), там значения могут
отличаться в зависимости от разрядности ячейки памяти. Но в любом случае "концовка
строки" совпадает.
14. Перевод отрицательных чисел из любой системы счисления в десятичную
function SystemNumNAto10(s: string; a: byte): int64;
var i, k, len: byte;
max, step: int64;
begin
Result:=0;
if (a<2) or (a>36) then
Exit;
case a of
2: len:=8;
3: len:=5;
4..6: len:=4;
7..15: len:=3;
else
len:=2;
end;
k:=Length(s) div len;
len:=Length(s) mod len;
if len>0 then
k:=k+len; // 1 (байт)
k:=8*k-1; // 7 (бит)
max:=int64(1) shl k - 1; // 127
Result:=SystemNumAto10(s, a);
if Result>max then
begin
Result:=0;
step:=1;
for i:=Length(s) downto 1 do
begin
k:=SystemNumByte(s[i]);
k:=a-k-1;
Result:=Result+k*step;
step:=step*a;
end;
Result:=-Result-1;
end;
end;
где:
s – исходное число любой системы счисления, записанное в
строковом виде;
a – система счисления.
Например,
SystemNumNAto10('11110110', 2) выведет
'-10';
SystemNumNAto10('8000', 16) выведет
'-32768'.
Примечание. Важное для всех функций! Если в
некоторых версиях языка Паскаль целочисленных тип int64 отсутствует,
то его можно заменить на integer . Правда диапазон чисел уменьшится
на 4 байта.
|