belarusweb.net - веб-программирование для новичков: HTML,CSS, JavaScript, PHP, MySQL и др.

# Перевод чисел из одной системы счисления в другую.

В повседневной жизни мы привыкли иметь дело с десятичной системой счисления, в которой числа образуются при помощи цифр 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Однако современные компьютеры на аппаратном уровне работают только с цифровыми данными представленными в двоичной системе счисления, в которой числа образуются при помощи двух цифр 0 и 1. Это связано с тем, что компьютеры для обработки информации используют устройства, которые могут принимать только два различных устойчивых состояния, например, заряжен или не заряжен, намагничен или не намагничен, есть ток или нет тока и т.д. Одно из состояний устройства принимается за ноль, а другое – за единицу. После объединения множества таких простейших устройств в одно сложное, например, процессор, как раз и появляется возможность обрабатывать данные в виде чисел в двоичной системе счисления. Но поскольку двоичные числа очень длинные, то для более короткой и удобной их записи при составлении программ на языке машинных кодов используются промежуточные восьмеричная и шестнадцатеричная системы счисления, числа в которых образуются, соответственно, при помощи цифр 0, 1, 2, 3, 4, 5, 6, 7 и 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. Все это приводит к тому, что в ходе написания программ время от времени появляется необходимость перевода чисел из одной системы счисления в другую. Рассмотрением данного вопроса мы как раз и займемся в данной статье.

Перевод целых чисел и правильных дробей из десятичной системы счисления в систему счисления с основанием 'n' производится по разным правилам. Поэтому для вещественного числа, которое имеет целую и дробную части, для перевода целой части применяется правило перевода целых чисел, а для перевода дробной части – правило перевода правильных дробей. Рассмотрим все случаи по отдельности.

1. Для перевода целых чисел из десятичной системы счисления в систему счисления с основанием 'n' используется следующий алгоритм.

- Исходное десятичное число a делится нацело на основание n, в результате чего получается частное c_1 и остаток от деления r_1, который фиксируется.
- Далее, частное c_1 вновь делится на основание n, остаток r_2 фиксируется, а вся процедура повторяется заново до тех пор, пока частное не станет равным нулю (частное, а не остаток!).
- В самом конце из полученных остатков, записанных в порядке, обратном их получению, составляется требуемое число в новой системе счисления с основанием 'n'.

В качестве примера рассмотрим перевод числа 35 из десятичной системы счисления в двоичную, восьмеричную и шестнадцатеричную:

    	35:2=17 (остаток 1) //фиксируем 1
    	17:2=8  (остаток 1) //фиксируем 1
    	 8:2=4  (остаток 0) //фиксируем 0
    	 4:2=2  (остаток 0) //фиксируем 0
    	 2:2=1  (остаток 0) //фиксируем 0
    	 1:2=0  (остаток 1) //фиксируем 1
    	 --------------------------------
    	 Результат: 3510=1000112.

    	35:8=4 (остаток 3) //фиксируем 3
    	 4:8=0 (остаток 4) //фиксируем 4
    	 --------------------------------
    	 Результат: 3510=438.

    	35:16=2 (остаток 3) //фиксируем 3
    	 2:16=0 (остаток 2) //фиксируем 2
    	 --------------------------------
    	 Результат: 3510=2316.

2. Для перевода правильных дробей из десятичной системы счисления в систему счисления с основанием 'n' алгоритм имеет другой вид.

- Исходное десятичное число a, модуль которого меньше единицы (|a|<1), умножается на основание n, после чего целая часть результата произведения фиксируется.
- Далее, дробная часть результата вновь умножается на основание n, целая часть нового результата фиксируется, а вся процедура повторяется заново до тех пор, пока дробная часть очередного результата не станет равной нулю либо не будет достигнута требуемая точность числа в новой системе счисления с основанием n.
- В самом конце составляется требуемое число в новой системе счисления. Для этого записывается нулевая целая часть числа, а затем из зафиксированных ранее целых частей, при чем в той последовательности, в которой они были получены, составляется его дробная часть.

Отметим, что целые числа могут быть точно переведены из одной системы счисления в другую, чего не скажешь о дробных числах, которые в общем случае не могут быть переведены без потери точности. Поэтому очень важно при переводе дробных чисел уметь правильно определять в конечном числе количество разрядов после запятой, которые обеспечат нам требуемую точность. Добиться этого можно исходя из того, что число будет иметь одинаковую точность в различных системах счисления, если веса младших разрядов числа в этих системах будут одинаковы.

Вес P младшего разряда числа в текущей системе счисления, т.е. точность, которую обеспечивает данный разряд, определяется по формуле P=1/(nk), где n - основание системы счисления, k - количество разрядов после запятой. Следовательно, для двух систем счисления равенство весов будет иметь вид: 1/(n_1k_1)=1/(n_2k_2), откуда требуемое минимальное количество разрядов числа после перевода будет равно k_2=k_1/(logn_1n_2). Например, вес младшего разряда числа 0.6 в десятичной системе счисления будет равен 1/(101)=0.1. Поэтому, для сохранения точности числа в случае перевода его в двоичную систему счисления, количество разрядов числа должно быть не меньше 4, т.к. 1/(log102)≈1/0.3≈3.3.

Рассмотрим в качестве примера перевод числа 0.3 из десятичной системы счисления в двоичную, восьмеричную и шестнадцатеричную.

    	Требуемое количество разрядов k2=4, т.к. 1/lg2≈3.3.

    	0.3*2=0.6 (целая часть равна 0) //фиксируем 0
    	0.6*2=1.2 (целая часть равна 1) //фиксируем 1
    	0.2*2=0.4 (целая часть равна 0) //фиксируем 0
    	0.4*2=0.8 (целая часть равна 0) //фиксируем 0
    	--------------------------------
    	 Результат: 0.310=0.01002.

    	Требуемое количество разрядов k8=2, т.к. 1/lg8≈1.1.

    	0.3*8=2.4 (целая часть равна 2) //фиксируем 2
    	0.4*8=3.2 (целая часть равна 3) //фиксируем 3
    	--------------------------------
    	 Результат: 0.310=0.238.

    	Требуемое количество разрядов k16=1, т.к. 1/lg16≈0.83.

    	0.3*16=4.8 (целая часть равна 4) //фиксируем 4

    	--------------------------------
    	 Результат: 0.310=0.416.

3. В общем случае для перевода вещественных чисел из десятичной системы счисления в систему счисления с основанием 'n' следует отдельно перевести его целую и дробную части, а затем дописать дробную часть к целой. Например, для числа 35.310 получим:

    	35.310=1000112+0.01002=100011.01002;
    	35.310=438+0.238=43.238;
    	35.310=2316+0.416=23.416.

4. Из всего выше сказанного следует, что перевод числа из системы счисления с основанием 'n' в систему счисления с основанием 'm' можно осуществить в два этапа:

- в начале переводим число в десятичную систему счисления;
- а затем в нужную нам систему счисления с основанием 'm'.

При этом не нужно забывать, что в общем случае при переводе дробных чисел из одной системы счисления в другую теряется точность.

Теперь давайте рассмотрим перевод чисел из системы счисления с основанием 'n' в десятичную систему счисления. Начнем с того, что в общем случае число c в позиционной системе счисления может быть разложено по степеням своего основания 'n' и представлено в виде полинома в десятичной системе счисления:
c = ma-1*na-1 + ma-2*na-2 +...+ m1*n1 + m0*n0 + m-1*n-1 +...+ m-b*n-b , где
n – основание исходной системы счисления;
mi – значение цифры в i-ом разряде исходного числа, где i изменяется от -b до a-1;
a – количество разрядов целой части в исходном числе;
b – количество разрядов дробной части в исходном числе.

Таким образом, для перевода числа из системы счисления с основанием 'n' в десятичную систему счисления нужно представить его в виде данного полинома, а затем вычислить получившуюся сумму.

В качестве примеров переведем числа наших примеров обратно в десятичную систему счисления.

    100011.01002 = 1*25 + 0*24 + 0*23 + 0*22 + 1*21 + 1*20 + 0*2-1 + 1*2-2 + 0*2-3 + 0*2-4 = 35.2510;
    43.238 = 4*81 + 3*80 + 2*8-1 + 3*8-2 = 35.2910;
    23.416 = 2*161 + 3*160 + 4*16-1 = 35.2510.

Как видим, в результате обратных преобразований мы не получили то число, которое ожидали. Это связано с появлением погрешности в ходе преобразований чисел из десятичной системы счисления. Поэтому для повышения точности преобразований нужно брать не минимально возможное число разрядов, а несколько большее, в зависимости от необходимой точности.

Отдельно рассмотрим перевод чисел из системы счисления с основанием 2n в систему счисления с основанием 2m и обратно. Точнее говоря, мы подробно рассмотрим только переводы между двоичной, восьмеричной и шестнадцатеричной системами счисления, т.к. они широко применяются в программировании.

1. В общем случае перевод чисел из двоичной системы счисления в систему счисления с основанием 2n довольно прост и осуществляется по следующему общему алгоритму:

- разряды исходного двоичного числа группируются по n разрядов влево и вправо от запятой, разделяющей целую и дробную части;
- далее, неполные группы двоичных цифр по краям исходного числа дополняются незначащими нулями;
- после чего каждую из полученных групп двоичных цифр заменяют соответствующей ей цифрой системы счисления с основанием 2n.

Отметим, что для восьмеричной системы счисления разряды разбиваются на тройки, которые называют двоичными триадами, а для шестнадцатеричной – на четверки, которые называют двоичными тетрадами. Триады и тетрады вместе с соответствующими им цифрами в восьмеричной и шестнадцатеричной системах счисления представлены в следующей таблице:

Триада | Число N8 | Тетрада | Число N16
--- | --- | --- | ---
000 | 0 | 0000 | 0
001 | 1 | 0001 | 1
010 | 2 | 0010 | 2
011 | 3 | 0011 | 3
100 | 4 | 0100 | 4
101 | 5 | 0101 | 5
110 | 6 | 0110 | 6
111 | 7 | 0111 | 7
– | – | 1000 | 8
– | – | 1001 | 9
– | – | 1010 | A
– | – | 1011 | B
– | – | 1100 | C
– | – | 1101 | D
– | – | 1110 | E
– | – | 1111 | F

Для наглядности рассмотрим пример перевода числа 10110010011,11010101100011 в восьмеричную и шестнадцатеричную системы счисления, используя указанный алгоритм и таблицу триад и тетрад:

    10110010011,11010101100011 -> 010 110 010 011,110 101 011 001 100 -> 2623.653068;
    10110010011,11010101100011 -> 0101 1001 0011,1101 0101 1001 1000 -> 593.D58C16.

2. Для перевода чисел из восьмеричной и шестнадцатеричной систем счисления в двоичную нужно:

- заменить каждую цифру числа соответствующей двоичной триадой или тетрадой (воспользовавшись таблицей выше);
- и далее, опустить незначащие нули в старших разрядах целой части и младших разрядах дробной части.

В качестве примера осуществим обратный перевод чисел предыдущего примера в двоичную систему:

    2623.653068 -> 010 110 010 011,110 101 011 001 ->
    010010110010011,11010101100011 -> 10010110010011,11010101100011;

    593.D58C16 -> 0101 1001 0011,1101 0101 1001 1000 ->
    010110010011,1101010110011000 -> 10110010011,11010101100011.

В конце добавим, что перевод чисел из восьмеричной системы счисления в шестнадцатеричную или обратно, можно осуществить в два этапа:

- в начале переводим число в двоичную систему счисления;
- а затем в нужную нам восьмеричную или шестнадцатеричную систему счисления.

belarusweb.net © Петр Романовский, Минск, 2016.