Пример 4: Упорядочение массива по возрастанию




 

Это пример, мы разберём подробно.

Выше уже было разъяснено, как организуется ввод. Поэтому договоримся о том, что перед вводом текста программы, мы уже осуществили ввод данных таким образом, что на вершине стека лежит число - количество элементов массива и под ним лежат все элементы массива.

Мы воспользуемся циклом DO. Для него на вершине стека должны лежать два значения начальное значение параметра и его конечное значение. Запишем команды, которые создадут необходимую структуру стёка.

 

DUP

SWAP


Запишем изменения вершины стека, которые происходят в процессе выполнения этих команд.

 

Команда 1: N N

Команда 2: 1 N N

Команда 3: N 1 N

Команда 4: 1 N 1 N

 

Таким образом, требуемая структура сформирована и можно записать заголовки цикла

 

DO

DO

 

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

 

2DUP

>

 

Первый оператор дублирует одно двойное слово или что-то же самое два одинарных, то есть дублирует на вершине стёка два значения. Затем операция "больше" снимает два значения, назовём их А, В и если А > В то кладёт на вершину стёка единицу иначе кладёт ноль. Если на вершине стека единица, то А и В находятся в нужном порядке и ничего делать не надо, иначе их нужно поменять местами

 

IF

ELSE

SWAP

THEN

 

Оператор IF снимает со стека 1 или 0 (результат операции сравнения), если снята единица то ничего не происходит иначе два верхних элемента, а это опять А и В меняются местами. И теперь осталось провернуть стёк. Для этого необходимо выполнить команду N ROLL. Если N - количество элементов массива, то команда осуществит необходимый нам сдвиг стёка. Ясно, что нам опять нужно значение N, но оно было безвозвратно снято со стёка и забыто (о нём сейчас помнят только заголовки циклов). Вот тут мы сможем с пользой применить понятие переменной. Чтобы запомнить в оперативной памяти значение N мы в самом начале программы должны выполнить следующее

 

DUP

VARIABLE N

!

 

Это фрагмент дублирует значение N лежащее на стёке, следующая команда (Variable) резервирует в необходимое количество ячеек памяти и старший адрес зарезервированной области кладёт на стёк. Восклицательный знак снимает два значения со стека (адрес и значение N) и значение пересылает по адресу. Если теперь нам необходимо получить значение переменной N мы должны выполнить следующее:

 

N @

 

N - теперь воспринимается как команда языка Форт с её выполнением на стек ложится значение адреса памяти по которому хранится значение переменной. Знак собачки снимает со стека значение адреса, затем пересылает значение, взятое по этому адресу, на вершину стека и теперь мы можем выполнить команду ROLL. Она снимет со стека значение N и осуществит требуемый сдвиг массива.

И осталось завершить циклы

 

LOOP

LOOP

 

Если есть потребность просмотреть массив, необходимо вывести все элементы стека на экран циклическим повторением команды точка.

 

N @ (кладем на стек количество элементов массива)

1 (Кладем на стёк начальное значение параметра цикла)

DO (Снимаем со стека параметры цикла и начинаем работу)

. (Снимаем очередной элемент стека)

LOOP (Переходим к новому шагу цикла)

 

Запишем полученную программу целиком

 

(Создание переменной)

DUP

VARIABLE N

!

(Создание необходимой структуры данных для организации циклов)

DUP

SWAP

(Обработка массива)

DO

DO

2DUP

>

IF

ELSE

SWAP

THEN

N @

ROLL

LOOP

LOOP

(Вывод массива для просмотра)

N @

DO

.

LOOP

 

Определяющие слова

 

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

Конечно, те операции, которые приклеиваются к базовым типам, реализуются разработчиком компилятора и они для изменения недоступны, и конечно, нельзя допустить, чтобы программист - пользователь компилятора имел возможность менять код компилятора, но операцию можно реализовать и средствами самого языка высокого уровня. Это будет почти та же самая процедура или функция языка, с той лишь разницей, что она будет жёстко привязана к конкретным данным. Если таким образом к стандартному типу данных (такому как мы рассматривали в первой лекции) добавить набор процедур и функций, то получится совершенно новая языковая структура именуемая объектом. Объект хорошо тем, что в нём полностью описывается всё, что нужно для понимания его смысла, обработки, размещения в памяти, поэтому программа, построенная из объектов, становится более понятной и более прозрачной для восприятия. Такой подход широко распространён. Это сейчас называется объектным программированием, а язык Форт - это один из первых языков, где прозвучала идея объектного программирования. Правда в Форте нет терминов используемых ныне: объект, класс, инкапсуляция и т.д., но ведь это одна из первых попыток! А теперь перейдём к Форту.

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

Синтаксис определяющего слова

 

CREATE > СОЗДАВАЕМАЯ ЧАСТЬ

DOES > ИСПОЛНЯЕМАЯ ЧАСТЬ

 

Рассмотрим в качестве примера определение понятия вектор. При создании вектора будем указывать размер (число элементов), а при обращении к нему - индекс элемента, в результате чего получается адрес данного элемента. Этот адрес можно разыменовать и получить значение элемента или можно заслать по этому адресу новое значение. Если желательно контролировать правильность индекса при обращении к вектору, то определение может выглядеть так:

; Вектор CREATE DUP, 2*ALLOT

DOES >

OVER 1- OVER U< (Проверка индекса)

IF SWAP 2 * + EXIT THEN

. "Ошибка в индексе"

 

Рассмотрим, как работает данное определение при создании вектора 10 вектор Х.

Создающая часть компилирует размер вектора и вслед за этим отводит память на 10*2 байт. Таким образом, в словаре для вектора Х отводится размером 22 байта, в первых двух байтах хранится число 10 - размер вектора. При обращении к вектору Х на стеке должно находиться значение индекса. Слово DOES> кладёт сверху адрес области сформированной создающей частью, после чего работает исполняющая часть определения. Проверив, что индекс лежит в диапазоне между 1 и 10, она оставляет на стёке адрес, равный начальному адресу области плюс I*2 то есть адрес I - го элемента вектора, если считать, что элементы располагаются в зарезервированной области подряд. Если окажется, что индекс не положителен или больше числа элементов, то будет напечатано сообщение "Ошибка в индексе" и исполнение закончится через слово ABORT.


Заключение

 

Вспомним, что первые компьютеры обладали очень ограниченной памятью. Это было так не только из-за дороговизны оперативной памяти и даже не столько из-за неё, сколько из-за ограниченной возможности процессора адресовать память. Разрядность процессора налагает на величину максимального адреса очень жесткое ограничение. Если же основная масса памяти организована в виде стека, то проблема адресации уходит, так как запоминать необходимо только одну ячейку - вершину стека. Ещё одна крайне интересная особенность Форта видна в первых трёх примерах. Достаточно сложные вычислительные процессы идут совершенно без использования понятия переменной. Такая организация памяти, как уже упоминалось, существенным образом влияет на организацию подпрограмм. В некотором смысле их нет, а есть поток заданий, каждое из которых может представлять собой подпрограмму с точки зрения пользователя, чтобы понять механизм такого действа, нужно более тщательно рассмотреть работу Форт системы в целом, что уже выходит за рамки данной работы.


Литература

 

1. Вострикова З.П. и др. "Программирование на языке "БЕЙСИК" для персональных ЭВМ". Машиностроение, 1993г.

2. Гохман А.В. и др. "Сборник задач по математической логике и алгебры множеств", издательство Саратовского Университета, 1969г.

3. Гусев В.В. Основы импульсной техники. М. Советское радио, 1975

4. Касаткин В.Н. "Информация, алгоритмы, ЭВМ", М. Просвещение, 1991г.

5. Машовцев В.А. Вступительные экзамены по информатике//Информатика. 1997, №13

6. Орлов В.А. О вступительных экзаменах по информатике//Информатика, 1997, №15

7. Яснева Г.Г. Логические основы ЭВМ//Информатика и образование, 1998, №2

8. Лыскова В.Ю., Ракитина Е.А. Логика в информатике, М. Информатика и образование 1999

9. Шауцкова Л.З. “Решение логических задач средствами алгебры логики”, газета Информатика 1999, №5.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-06-03 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: