Данному образовательному сайту пришлось несколько раз менять свое имя. С 2022 года доступ к нему обеспечивается по URL
emc.km.ru (2001-2007) ==> educomp.org.ru (2007-2011) ==> educomp.runnet.ru (2011-2021) ==> emc.orgfree.com (2022-...)
Более подробно об истории сайта можно прочитать здесь.
|
У компьютера своя информатикаМы знаем тысячи разрозненных фактов, и часто рассматриваем их изолированно друг от друга, не задумываясь о том, что все они должны быть как-то связаны, поскольку мир вокруг нас един. Например, любому ребенку известно (факт А), что летом тепло, а зимой холодно. Кроме того, не менее очевидно (факт Б), что чем ближе к Солнцу, тем теплее. Каждый из тезисов очевиден и неоспорим, оба, вроде бы, об одном и том же, но при попытке объединить А и Б вместе вдруг возникают трудности: а почему же тогда сейчас, когда у нас в северном полушарии зима, в Австралии лето? По данным статьи [1], которая представляет собой стенограмму выступления А. Кэя1 в Конгрессе США, почти 95% старшекурсников и профессоров некоторых ведущих университетов этой страны в ходе проведенного опроса уверенно утверждали, что «Земля летом ближе к Солнцу, чем зимой». А на последующий вопрос «Знаете ли вы, какое время года настает в Южной Америке и Австралии, когда у нас в Штатах приходит лето?» давали не менее уверенный ответ «Зима, разумеется». Причем противоречие нового названного факта предыдущим двум мало кто замечал… А. Кэй пишет, что “мы столкнулись с отсутствием у этих ребят самых элементарных навыков критического мышления. Ведь и им, и их наставникам, не выдержавшим испытания, были известны факты, противоречащие невразумительным догадкам. Почему же никто из них не спохватился: «Эй, послушайте, как же так?..» Все, что нужно для правильного ответа, было им известно! Однако сопоставить факты, сложить из них мозаику, которая станет правильным ответом, большинству участников испытания не удалось.” Таким образом, умение сопоставлять известные факты между собой является важным признаком умственного развития. А нет ли в информатике подобных примеров, когда сопоставление фактов первоначально приводит к противоречию, а последующий анализ позволяет лучше разобраться в сути проблемы?
Рассмотрим следующий, казалось бы, избитый, классический вопрос о переводе из десятичной системы в двоичную и обратно (договоримся для краткости записи называть эти процедуры «10 в 2» и «2 в 10»). Редкая книга по информатике, исключая, может быть, самоучители для «чайников» или «полных идиотов», не рассказывает о том, как это делается. Трудно противостоять напору информации и не знать (факт А): для перевода «10 в 2» необходимо число последовательно делить на два, а «2 в 10» выполняется путем сложения соответствующих степеней двойки. Мне просто не хочется писать об этом подробнее, чтобы не вызвать зевоту у читателей. Что касается факта Б, то он, видимо, менее известен широкой аудитории, но для меня он не менее очевиден, чем факт А. Речь идет о том, по какому алгоритму в компьютере на практике осуществляется перевод. О деталях поговорим чуть позднее, а сейчас подумаем, как должны быть связаны факты А и Б? Иначе говоря, использует ли компьютер те же самые алгоритмы, которые мы так старательно изучали на уроках? Увы, ответ если и не отрицательный, то весьма далекий от положительного. Словом, компьютер осуществляет перевод не совсем так, как это делаем мы с вами! Причин тому несколько. Во-первых, компьютер приводит к двоичному виду не десятичное число, а его введенное с клавиатуры текстовое отображение2. Во-вторых, при проведении расчетов мы пользуемся десятичной системой, а компьютер двоичной (чуть позднее мы увидим, что это приводит к весьма существенным последствиям при выборе алгоритма). Наконец, в третьих, мы производим перевод чисел редко, поэтому не заботимся об оптимальности вычислительного процесса, а для компьютера ситуация другая. Таким образом, задачи «10 в 2» и «2 в 10» для человека и для компьютера выглядят весьма по-разному. Рассмотрим теперь реализацию процесса перевода в компьютере подробнее. В основе перевода из одной системы счисления в другую лежит следующая общая теорема (см., например, [2]).
Если формулировка кажется вам запутанной и устрашающей, положите везде p = 10 и d = 2 (слова «записанное в той же p-ичной системе» в данном случае становятся излишними), в результате чего получится известное всем правило перевода «10 в 2». Необычайно важно понять, что данный алгоритм в принципе пригоден для перевода между абсолютно произвольными системами счисления. Проблема заключается в последней фразе – действия необходимо производить в той же системе, в которой представлено исходное число. Отсюда следует важный для нас сейчас вывод, что для человека данное правило удобно лишь при p = 10, т.е. при переводе из десятичной системы. Поэтому, хотя теорему можно применять и для «2 в 10», осуществляя все расчеты в двоичной системе, но делать это гораздо проще, используя другой (известный из школы) алгоритм. Что касается компьютера, то ему, напротив, удобнее производить вычисления в двоичной системе. Поэтому для перевода «2 в 10» используется последовательное деление на десять в двоичной системе, а «10 в 2» – сложение степеней десятки. Таким образом, в компьютере уже известные нам методы применяются «зеркальным» образом по сравнению с тем, как их использует человек. И еще об одной особенности перевода «10 в 2» в компьютерной реализации. Рассмотрим ее на примере конкретного числа 1234. Для упрощения вычислений данное выражение удобно преобразовать путем вынесения множителя 10 за скобки. Получим: Повторим процедуру еще раз. Присмотревшись повнимательнее, увидим, что получившаяся формула описывает последовательное умножение предыдущего результата Rk-1 на 10 и прибавление очередной цифры ck: Заметим, что в качестве начального условия удобно принять R0 = 0. Формула (2) по сравнению с исходным выражением (1) имеет существенные преимущества. Во-первых, она не требует запоминания промежуточного результата, а сразу использует его для дальнейших вычислений. Во-вторых, как доказали математики, такая схема вычислений, называемая схемой Горнера, содержит минимально возможное число арифметических операций. Наконец, в-третьих, формула (2) корректно обрабатывает число по мере ввода, тогда как (1) требует, чтобы все цифры были уже известны (иначе нельзя расставить степени!); в некоторых программах такое свойство оказывается полезным. Примечание. Схема Горнера оказывается удобной и при традиционном «ручном» переводе «2 в 10». Более того, из ее записи немедленно видно, почему последовательное деление на 2 при обратной процедуре «10 в 2» дает именно двоичные цифры (подробнее см. главу 6 в [3]). Напомнив читателям еще раз о том, что процедура «10 в 2» переводит текстовую строку с десятичным представлением числа в двоичное число, а «2 в 10» наоборот, приведем текст программ перевода, для наглядности реализованных на Паскале. Они настолько просты, что в дополнительных комментариях не нуждаются. Листинг 1.
{10 в 2}
CONST baza=ord('0'); {код символа '0'}
VAR s: STRING; r, i: INTEGER;
BEGIN READLN(s); {строка с десятичным числом (без ошибок!)}
i:=1;{номер символа} r:=0;{очистим будущий результат}
WHILE i<=LENGTH(s){до конца строки} DO
BEGIN r:=10*r+(ord(s[i])-baza); {добавим цифру к результату}
i:=i+1; {к следующему символу}
END;
WRITELN(r); {вывод результата – должен совпасть со введенным}
END.
Листинг 2.
{2 в 10}
CONST baza=ord('0'); {код символа '0'}
VAR s: STRING; n, i: INTEGER;
BEGIN READLN(n); {в переменной n - двоичное число}
s:=''; {пока пусто}
WHILE n>0 DO
BEGIN i:=n MOD 10; s:=CHR(i+baza)+s; {очередная цифра}
n:=n DIV 10; {оставшиеся цифры}
END;
WRITELN(s); {вывод результата – должен совпасть со введенным}
END.
Хочу особо подчеркнуть, что описанная в статье картина распространяется не только на языки программирования; все сказанное выше, например, целиком и полностью относится ко вводу числовой информации в ячейки электронной таблицы Excel. Кстати говоря, при достаточном знании строковых функций, листинги 1 и 2 можно переделать для имитации рассматриваемых алгоритмов в Excel. Ниже в таблицах 1 и 2 кратко описано, как заполнить ячейки таблицы для того, чтобы проанализировать ход перевода для случая, когда количество десятичных цифр не превышает четырех. Заметим, что столбец A оставлен для нумерации цифр числа (в таблице не отражено). Таблица 1.
Таблица 2.
Тем читателям, которые захотят взглянуть на реализацию проблемы перевода чисел в компьютере IBM PC на языке процессора, могу порекомендовать доступную начинающим книгу [4].
Подведем итоги. Как оказалось, алгоритмы перевода «10 в 2» и «2 в 10» в компьютере реализуются на практике не так (или, выражаясь мягче, не совсем так), как нас учат в книгах. Но это имеет под собой вполне логичное объяснение: нас учат, как удобнее выполнять действия человеку. Что же касается компьютера, то у него «своя информатика» – двоичная, и «человеческие» десятичные алгоритмы ему не всегда подходят. С моей точки зрения, это один из примеров, который наглядно демонстрирует тот факт, что попытки «умозрительно» описывать поведение компьютера на основе повседневного (десятичного и неформального) человеческого опыта без знания фундаментальных технических подробностей могут приводить к абсолютно неправильным представлениям. К сожалению, повсеместный переход к «юзеровскому» способу обучения делает последний тезис все более актуальным. Примечание. Кстати говоря, в учебниках все делается аккуратно и хитро: сначала идет глава с абстрактной математической теорией систем счисления, где компьютер вообще не упоминается, а затем следует глава об устройстве компьютера, в которой говорится, что методы перевода базируются на изложенной ранее теории, и поэтому мы их не рассматриваем. А что получается при формальном применении «изложенной ранее теории», мы с вами сегодня видели! В заключение сформулируем выводы.
Литература
1 автор первой объектно-ориентированной среды программирования Smalltalk; многие годы Кэй работал преподавателем в школах Калифорнии 2 кто не видит разницы, путь вспомнит, что 12 + 34 = 46, а «12» + «34» = «1234»! 3 современный курс информатики в школе чаще всего строится по принципу фундаментальная теория (информация, системы счисления и т.д.) – отдельно, практика (MS Office) – отдельно; в то же время, принципы работы компьютера, которые во многом являются связующим звеном того и другого – 16 часов с 7 по 11 класс, включая правила ТБ, ОС и основы ПО Приложения1. Файл Excel с таблицами 1 и 2. 2. Ниже приведены программы перевода на ассемблере Intel, "обернутые" в Turbo Pascal На Free Pascal тоже так можно делать. Важно только не забыть указать, что ассемблер Intel. Листинг 1
program p10v2_asm;
uses wincrt;
var s:string; n:integer;
begin readln(s);
ASM LEA BX,s {адрес переменной s в BX}
MOV CL,[BX] {s[0]=length(s) }
MOV CH,0 { поместим в CX}
INC BX {BX на первый символ}
XOR AX,AX {0 ==> AX (результат)}
@1: MOV DX,0Ah {10 ==> DX}
MUL DX {*10}
MOV DL,[BX] {извлечь очередной символ}
SUB DL,30h {преобразовать его в число}
ADD AX,DX {прибавить к результату}
INC BX {BX + 1 - к следующему символу}
LOOP @1 {CX - 1; если не 0 - к повторению цикла}
MOV n,AX {результат в переменную n}
END;
writeln(n)
end.
Листинг 2 program p2v10_asm;
uses wincrt;
var n:integer; s:string;
begin readln(n);
ASM MOV AX,n {значение переменной n в AX}
XOR CX,CX {0 ==> CX (счетчик цифр)}
MOV BX,0Ah {10 ==> BX}
@1: XOR DX,DX {0 ==> DX (особенности деления процессора Intel
см., например, Нортон П., Соухэ Д.
Язык ассемблера для IBM PC. М.: Компьютер, 1992)}
IDIV BX {AX div BX ==> AX (остаток - в DX!)}
PUSH DX {запомним в стек, т.к. цифры получаются "с конца"}
INC CX {CX + 1 - еще одна цифра}
AND AX,AX {результат деления в AX нулевой?}
JNZ @1 {если нет - продолжать деление}
LEA BX,s {адрес переменной s в BX}
MOV [BX],CL {количество символов в s[0]=length(s)}
@2: INC BX {адрес следующего символа}
POP AX {достать очередной остаток из стека}
ADD AL,30h {сформировать цифру}
MOV [BX],AX {записать в переменную}
LOOP @2 {CX - 1; если не 0 - повторять цикл}
END;
writeln(s);
end.
© Е.А.Еремин, 2025 Еремин Е.А. У компьютера своя информатика. Информатика (газета Издательского дома "Первое сентября"), 2006, N 9, с.37-40; N 10, с.38. |