В повседневной жизни мы привыкли иметь дело с десятичной системой счисления, в которой числа образуются при помощи цифр 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' используется следующий алгоритм.
В качестве примера рассмотрим перевод числа 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' алгоритм имеет другой вид.
Отметим, что целые числа могут быть точно переведены из одной системы счисления в другую, чего не скажешь о дробных числах, которые в общем случае не могут быть переведены без потери точности. Поэтому очень важно при переводе дробных чисел уметь правильно определять в конечном числе количество разрядов после запятой, которые обеспечат нам требуемую точность. Добиться этого можно исходя из того, что число будет иметь одинаковую точность в различных системах счисления, если веса младших разрядов числа в этих системах будут одинаковы.
Вес 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' можно осуществить в два этапа:
При этом не нужно забывать, что в общем случае при переводе дробных чисел из одной системы счисления в другую теряется точность.
Теперь давайте рассмотрим перевод чисел из системы счисления с основанием '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 довольно прост и осуществляется по следующему общему алгоритму:
Отметим, что для восьмеричной системы счисления разряды разбиваются на тройки, которые называют двоичными триадами, а для шестнадцатеричной – на четверки, которые называют двоичными тетрадами. Триады и тетрады вместе с соответствующими им цифрами в восьмеричной и шестнадцатеричной системах счисления представлены в следующей таблице:
Триада | Число 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.
В конце добавим, что перевод чисел из восьмеричной системы счисления в шестнадцатеричную или обратно, можно осуществить в два этапа: