Программирование на visual basic
Скачать 1.19 Mb.
|
11.3. Перевод натуральных чисел в системы счисления, кратные двоичной Вся информация в компьютере представляется в двоичной системе. Двоичная система удобна для компьютера, но не удобна для человека. Числа получаются очень длинными и визуально похожими друг на друга. Поэтому обычно программисты выводят двоичные числа в шестнадцате- ричной или восьмеричной системах счисления. Перевод из этих систем в двоичную и обратно легко может быть выполнен в уме. Перевод десятичного числа A в систему счисления с основанием p тре- бует 1+[log p A] операций деления. При этом количество цифр числа A p на единицу больше целой части log p A. Следовательно, при переводе большо- го десятичного числа A в шестнадцатеричную систему счисления требует- ся в четыре раза меньше операций деления, чем при переводе этого же числа в двоичную систему счисления. При ручном переводе десятичных чисел в двоичные обычно вначале десятичное число переводят в шестна- дцатеричное, а затем полученное шестнадцатеричное число переводят в двоичное. Алгоритм перевода из шестнадцатеричной системы в двоичную: 1. Вместо каждой шестнадцатеричной цифры пишем ее четырехзнач- ный код в двоичном виде по табл. 11.1. Таблица 11.1 0 1 2 3 4 5 6 7 0000 0001 0010 0011 0100 0101 0110 0111 8 9 A B C D E F 1000 1001 1010 1011 1100 1101 1110 1111 2. В полученном двоичном числе убираем ведущие нули, если они имеются. Пример. Число 3169789 перевести в двоичную систему счисления. 1) По приведенному выше алгоритму, производя шесть операций де- ления на 16, получаем шестнадцатеричное число 305dfd 16 130 2) Вместо каждой шестнадцатеричной цифры пишем ее четырехраз- рядный двоичный код по табл. 11.1: 0011 0000 0101 1101 1111 1101. 3) Убираем два ведущих нуля и получаем искомое двоичное число: 3169789 = 11 0000 0101 1101 1111 1101 2 11.3.1. Написать программу, переводящую шестнадцатеричное число в двоичное по приведенному выше алгоритму. Sub ПереводИзШестнадцатеричнойВДвоичную() Dim sHex As String, i As Long, sBin As String, mHex As Variant Dim c As String * 1, sHexAlph As String, L As Boolean ' Алфавит шестнадцатеричных цифр sHexAlph = "0123456789abcdef" ' Таблица четырехзначных двоичных кодов шестнадцатеричных ‘ цифр mHex = Array("0000", "0001", "0010", "0011", "0100", "0101", "0110", _ "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111") sHex = _ Trim(InputBox("Введите число в 16-ричной системе счисления")) For i = 1 To Len(sHex) 'Обход по всем цифрам числа ' LCase - перевести большие буквы в маленькие A в a, B в b, ... , ‘ F в f. ' i-тый символ шестнадцатеричного числа c = LCase(Mid(sHex, i, 1)) ' Логическое выражение истинное, если с – шестнадцатеричная ‘ цифра L = c >= "0" And c <= "9" Or c >= "a" And c <= "f" If Not L Then ' Контроль правильности i-той цифры Debug.Print "Ошибка. Цифра "; c; " во введенном числе "; _ sHex; " не восьмеричная." Exit Sub End If 'Добавление в sBin четырех двоичных символов, ‘соответствующих шестнадцатеричной цифре sBin = sBin + mHex(InStr(sHexAlph, c) - 1) Next i ' убрать ведущие нули. Вернуть правую часть строки sBin длиной ‘ меньшей на количество ведущих нулей ‘InStr(sBin, "1") – номер первого не нулевого бита sBin = Right(sBin, Len(sBin) - InStr(sBin, "1") + 1) Debug.Print "Шестнадцатеричное число "; sHex; _ " в Двоичной системе счисления равно "; sBin End Sub Алгоритм перевода из восьмеричной системы в двоичную: 1. Вместо каждой шестнадцатеричной цифры пишем ее трехзначный код в двоичном виде по табл. 11.2. Таблица 11.2 131 0 1 2 3 4 5 6 7 000 001 010 011 100 101 110 0111 2. В полученном двоичном числе убираем ведущие нули, если они имеются. Пример. Число 3169789 перевести в двоичную и восьмеричную системы счисления. 1) По приведенному выше алгоритму, производя восемь операций деления на 8, получаем восьмеричное число 14056775 8 2) Вместо каждой восьмеричной цифры пишем ее трехразрядный двоичный код по табл. 11.2: 001 100 000 101 110 111 111 101 3) Убираем два ведущих нуля и получаем искомое двоичное число. 3169789 = 1 100 000 101 110 111 111 101 2 11.3.2. Написать программу, переводящую восьмеричное число в двоичное. Sub ПереводИзВосьмеричнойВДвоичную() Dim sOct As String, i As Long, sBin As String, Oct As Variant Dim c As String * 1 Oct = Array("000", "001", "010", "011", "100", "101", "110", "111") sOct = _ Trim(InputBox("Введите число в восьмеричной системе счисления")) For i = 1 To Len(sOct) 'Обход по всем восьмеричным символам числа c = Mid(sOct, i, 1) ' i-тый символ восьмеричного числа If c < "0" Or c > "7" Then ' Контроль правильности введенных цифр Debug.Print "Ошибка. Цифра "; c; " во введенном числе "; _ sOct; " не восьмеричная." Exit Sub End If 'Добавление в sBin трех двоичных символов sBin = sBin + Oct(Val(c)) 'Соответствующих восьмеричной цифре Next i ' Убрать ведущие нули. Вернуть правую часть строки sBin , без ' ведущих нулей. InStr(sBin, "1") - возращает номер первой единицы sBin = Right(sBin, Len(sBin) - InStr(sBin, "1") + 1) Debug.Print "Восьмеричное число "; sOct; _ " в двоичной системе счисления равно "; sBin End Sub Алгоритм перевода из двоичной системы в шестнадцатеричную: 1. Начиная с младшего (правого) разряда, разбиваем двоичное число на группы по четыре двоичных цифры. Если в старшей (левой) группе не хва- тает цифр, добавляем необходимое количество ведущих нулей. 2. Вместо каждой полученной группы пишем одну шестнадцатеричную цифру согласно табл. 11.1. 132 11.3.3. Написать программу, переводящую двоичное число в шестна- дцатеричное. Sub ПереводИзДвоичнойВШестнадцатериричную() Dim mHex As Variant, sBin As String, i As Long, n As Long, k As Long Dim sHexc As String, sHex As String, sHexAlph As String ' алфавит шестнадцатеричных цифр sHexAlph = "0123456789abcdef" mHex = Array("0000", "0001", "0010", "0011", "0100", "0101", "0110", _ "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111") sBin = InputBox("Введите Число в двоичной системе счисления ") sBin = "000" + Trim(sBin) ' Добавить слева три нуля ' Сделать количество цифр в двоичном числе, кратным 4 sBin = Right(sBin, (Len(sBin) \ 4) * 4) ' Убрать лишние нули слева n = Len(sBin) For i = 1 To n \ 4 ' Обход по всем группам из 4 двоичных цифр sHexc = Mid(sBin, (i - 1) * 4 + 1, 4) 'Поиск соответствующей шестнадцатеричной цифры For k = 0 To 15 If sHexc = mHex(k) Then ' Нашли символ sHex = sHex + Mid(sHexAlph, k + 1, 1) ' Накопили в sHex Exit For ' Выйти из цикла For End If Next k Next i Debug.Print "Двоичное число "; sBin; _ " в Шестнадцатеричной системе счисления равно "; sHex End Sub Алгоритм перевода из двоичной системы в восьмеричную: 1. Начиная с младшего (правого) разряда, разбиваем двоичное число на группы по три двоичных цифры. Если в старшей (левой) группе не хватает цифр, добавляем необходимое количество ведущих нулей. 2. Вместо каждой полученной группы пишем одну восьмеричную циф- ру согласно табл. 11.2. Программу, реализующую данный алгоритм, предлагается написать читателям самостоятельно. Алгоритм перевода из восьмеричной системы счисления в шестнадцатеричную: 1. Перевести восьмеричное число в двоичное . 2. Полученное двоичное число перевести в шестнадцатеричное. 11.3.4. Написать программу, переводящую восьмеричное число в шест- надцатеричное по приведенному выше алгоритму. 133 Sub ПереводИзВосьмеричнойВШестнадцатериричную() Dim mHex As Variant, sHexc As String, sHex As String, _ sHexAlph As String, mOct As Variant, sOct As String, i As Long, _ sBin As String, n As Long, k As Long sHexAlph = "0123456789abcdef" ' алфавит цифр mOct = Array("000", "001", "010", "011", "100", "101", "110", "111") mHex = Array("0000", "0001", "0010", "0011", "0100", "0101", "0110", _ "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111") sOct = _ InputBox("Введите число в восьмеричной системе счисления ") For i = 1 To Len(Trim(sOct)) ' Перевод в двоичную систему sBin = sBin + mOct(Val(Mid(sOct, i, 1))) Next i ' Убрать ведущие нули sBin = Right(sBin, Len(sBin) - InStr(sBin, "1") + 1) ' Перевести с двоичной в шестнадцатеричную sBin = "000" + Trim(sBin) ' Добавить слева три нуля sBin = Right(sBin, (Len(sBin) \ 4) * 4) ' Убрать лишние нули слева n = Len(sBin) For i = 1 To n \ 4 sHexc = Mid(sBin, (i - 1) * 4 + 1, 4) For k = 0 To 15 If sHexc = mHex(k) Then sHex = sHex + Mid(sHexAlph, k + 1, 1) Next k Next i Debug.Print "Восьмеричное число "; sOct; _ " в Шестнадцатеричной системе счисления равно "; sHex End Sub Алгоритм перевода из шестнадцатеричной системы счисления в восьмеричную: 1. Перевести шестнадцатеричное число в двоичное . 2. Полученное двоичное число перевести в восьмеричное. 11.4. Перевод целых чисел в двоичный формат До сих пор мы переводили в различные форматы только положитель- ные числа. Целые отрицательные числа типа Integer и Long в памяти ЭВМ хранятся в дополнительном коде. Для того чтобы дать определения допол- нительного кода числа, необходимо ввести определение обратного кода целого числа. Для положительного целого числа типа Integer или Long прямой, об- ратный и дополнительный код совпадают, при этом первый бит равен 0. В отрицательном числе A в прямом, обратным и дополнительным ко- дах первый (знаковый) бит равен 1. В прямом коде числа A все незнако- вые биты совпадают с соответствующими битами положительного числа | A|. В обратном коде числа A все незнаковые биты инвертируются по от- 134 ношению к положительному числу | A|. Под инверсией понимается замена 0 на 1, а 1 на 0. Дополнительный код получается прибавлением 1 к млад- шему биту числа в обратном коде. В VB целые числа типа Byte бывают только положительными, хранятся в прямом коде, занимают 1 байт (8 бит) и находятся в диапазоне от 0 = 00000000 2 до 255 = 11111111 2 . При этом первый бит не является особым, т.е. все биты незнаковые. Числа типа Integer занимают 2 байта (16 бит). При этом первый бит определяет знак числа. Рассмотрим примеры представления чисел типа Integer в памяти ЭВМ. Самое малое число такого типа равно –32768=1000000000000000 2 = 8000 16 , а самое большое число 32767=0111111111111111 2 =7FFF 16 Примеры. Число -1999 представить в прямом, обратном и дополни- тельном коде. Решение. Переводим число 1999 в шестнадцатеричный код. 1999=07CF 16 . Число занимает 16 бит или четыре шестнадцатеричных циф- ры, причем первый бит знаковый. Прямой, обратный и дополнительные коды положительного числа 1999 совпадают и равны 0000 0111 1100 1111 2 . В прямом, обратном и дополнительном кодах отрицательного числа -1999 первый бит равен 1. В прямом коде числа –1999 все незнаковые биты совпадают с битами положительного числа 1999. Таким образом, –1999 = 1000 0111 1100 1111 2[п] В обратном коде числа –1999 все незнаковые биты инвертируются. -1999 = 1111 1000 0011 0000 2[о] Для получения дополнительного кода к двоичному числу в обратном коде добавляем 1. -1999 = 1111 1000 0011 0001 2[д] Хранение чисел в дополнительном коде удобно тем, что при сложении чисел любого знака получается число в дополнительном коде. При суммировании двух чисел в дополнительном коде действуют сле- дующие правила: 1) Двоичные числа складываются поразрядно справа налево по обыч- ным правилам арифметики двоичных чисел. При этом 0+0=0; 0+1=1+0=1; 1+1=0, и 1 переносится в старший разряд; 1+1+1 =1, и 1 переносится в старший разряд. 2) Если в разряд левее знакового переносится 1, то она теряется. 3) Если при сложении двух положительных чисел получается отрица- тельное число или при сложении двух отрицательных чисел получа- ется положительное число, то происходит ошибка переполнения. 4) Результатом является число в дополнительном коде. Пример. Сложить два числа A и B, а результат поместить в перемен- ную C. 1) A=3, B=-2. 135 A=0000 0000 0000 0011 2[д] , B=1000 0000 0000 0010 2[п] = = 1111 1111 1111 1101 2[п] = 1111 1111 1111 1110 2[д] 0000 0000 0000 0011 + 1111 1111 1111 1110 0000 0000 0000 0001 2) A=-3, B=2. A=1000 0000 0000 0011 2[п] = 1111 1111 1111 1101 2[д] B=0000 0000 0000 0010 2[д] 1111 1111 1111 1101 + 0000 0000 0000 0010 1111 1111 1111 1111 С=1111 1111 1111 1011 2[д] = 1111 1111 1111 1110 2[о] = 1000 0000 0000 0001 2[п] С=-1. 3) A=31773 , B=-15768. A=7C1D 16 , B=-3D98 16 A=0111 1100 0001 1101 2[д] . B = 1011 1101 1001 1000 2[п] = = 1100 0010 0110 0111 2[о] = 1100 0010 0110 1000 2[д] 0111 1100 0001 1101 + 1100 0010 0110 1000 0011 1110 1000 0101 С=3E85=16005. Для чисел типа Long действуют те же правила, что и для чисел типа Integer, только для них отводится 32 бита. При программировании на Visual Basic, для того чтобы извлечь любой бит, применяются битовые операции над числами. 11.4.1. Написать программу перевода числа A типа Byte в двоичную систему счисления. Решение. Возьмем двоичное число b=10000000 2 . Десятичное значение этого числа равно 2 7 = 128. Результатом побитовой операции A And b бу- дет 0, если первый бит числа A равен 0, и число 10000000 2 , если первый бит равен 1. В текстовую переменную s справа дописываем 0, если резуль- тат побитовой операции равен 0, и 1 – в противном случае. Затем делим число b на 2. Получаем число 64=01000000 2 . И опять применяем побито- вую операцию A And b и дописываем в s второй бит. И так до восьмого бита. Для удобства чтения результата между каждой четверкой битов вставляем пробел. Sub ПереводВДвоичныйФорматНаБитовыеОперацииByte() Dim a As Byte, b As Byte, i As Integer, s As String b = &H80 ' первый бит =1, остальные 7 равны 0. b=128 s = "" a = Val(InputBox("Введите целое число типа Byte")) For i = 1 To 8 ' В числе b i-тый бит = 1, остальные =0 136 If (a And b) = 0 Then s = s + "0" Else s = s + "1" If (i Mod 4) = 0 Then s = s + " " ' Через 4 бита пробел b = b / 2 'Сдвиг битов числа b на один вправо Next i Debug.Print s End Sub 11.4.2. Написать программу перевода числа A типа Long в двоичную систему счисления. Решение. Для чисел типа Long или Integer необходимо вначале опреде- лить значение первого бита, а затем в цикле определить незнаковые биты. Это связано с тем, что первый бит определяет знак числа, а при делении отрицательного числа на 2 получаем отрицательное число, в котором опять первый бит равен 1. Sub ПереводВДвоичныйФорматНаБитовыеОперации() Dim a As Long, b As Long, i As Integer, s As String ' Первый бит =1, остальные 32 равны 0 (1-вый бит знаковый) b = &H80000000 ' Для определения знака числа (первый бит) s = "" ‘ В переменной s будем накапливать биты числа a a =Val(InputBox(“Введите целое число”)) ‘Если число a отрицательно, то 1-ый бит =1 и (a And b)≠0 If (a And b) = 0 Then s = s + "0" Else s = s + "1" b = &H40000000 ' Второй бит =1, остальные 0 For i = 2 To 32 ‘ Обход по всем незнаковым битам от 2-го до 32-го ' В числе b i-тый бит = 1, остальные =0 If (a And b) = 0 Then s = s + "0" Else s = s + "1" If (i Mod 4) = 0 Then s = s + " " ' Через 4 бита пробел b = b / 2 'Сдвиг битов на один вправо Next i Debug.Print s End Sub 11.5. Перевод вещественных чисел в двоичный фор- мат Запись действительного числа A в p-ичной системе счисления пред- ставляется в виде последовательности цифр целой части, запятой и цифр дробной части, после которой на нижнем индексе записывается число p, указывающее основание системы счисления. A= α n α n-1 … α 1 α 0 ,α -1 α -2 … α m- 1 α m p . Где n, m ─ число цифр в целой и дробных частях. Это же число мож- но представить в виде суммы n+m+1-го слагаемого: A = p n +α n-1 p n-1 +…+α 1 p 1 +α 0 p 0 +α -1 p -1 + …+ α -(m-1) p -(m-1) + α -m p -m , (11.3) где α i – i-тая цифра числа. Для перевода данного числа в р-ичную систему счисления необходимо по отдельности перевести целую и дробную части числа, а затем их соеди- 137 нить. Алгоритм перевода целой части числа A рассмотрен в предыду- щих подразделах. Разработаем алгоритм перевода дробной части числа A в p-ичную систему. Обозначим дробную часть этого чис- ла буквой D. D = α -1 p -1 + … + α -(m-1) p -(m-1) + α -m p -m . (11.4) Чтобы получить первую цифру α -1 , необходимо число D умножить на основание p. pD = α -1 + α -2 p -1 + …+ α -(m-1) p -(m-2) + α -m p -(m-1) . Целая часть полученного числа является первой цифрой числа D. Для получения сле- дующей цифры α -2 , опять берем дробную часть числа D 1 = α -2 p -1 + …+ α -(m- 1) p -(m-2) + α -m p -(m-1) и проделаем те же операции. Такие операции проделыва- ем до тех пор, пока дробная часть D m будет положительной или достигнем необходимой точности. Теперь рассмотрим метод хранения вещественных чисел. Веществен- ные числа в памяти компьютера хранятся совсем иначе, чем целые. Суще- ствовало множество форматов хранения вещественных чисел. Причем на различных типах компьютеров был свой формат. В последнее время разра- ботан международный стандарт IEEE 754, который сейчас применяется практически на компьютерах всех типов. В данной работе рассмотрим стандарт хранения числа типа Single. Число типа Double хранится аналогично числам типа Single, только под порядок и мантиссу отводится больше бит, так как число типа Double за- нимают в два раза больше памяти. Зная диапазон изменения чисел типа Double, табл 1.1., читатель самостоятельно может определить количество бит, отведенных под порядок и мантиссу для чисел типа Double. Число ти- па Single занимает 4 байта или 32 бита. Следовательно, по логике, это чис- ло получается из 32 символов 0 или 1. На самом деле число типа Single, состоит из 33 бит. При этом применяется один скрытый бит. Согласно этому стандарту вещественное число |