Перейти к содержанию

Решение задач по программированию на языке Форт (Forth). Версия 3

Автор:

5,0 10+ оценок читателей Рунета
Категория
компьютерная справочная литература
Год издания
Издательство
Автор
Возрастное ограничение
12+
Обновлено
25.09.2026

Аннотация

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

Читать «Решение задач по программированию на языке Форт (Forth). Версия 3» — Arsen Gonian онлайн

Страница 4 из 7

FVAR F@ F.

12.340000 Ok

VAR и FVAR – это просто названия, они могут быть любыми другими – это просто удобное обозначение в стиле Форта. Теперь можем приступить к очередной задачке.

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

FVARIABLE FX1

FVARIABLE FY1

FVARIABLE FX2

FVARIABLE FY2

FVARIABLE FX3

FVARIABLE FY3

FVARIABLE FA

FVARIABLE FB

FVARIABLE FC

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

FVARIABLE FX1 FVARIABLE FY1 FVARIABLE FX2 FVARIABLE FY2 FVARIABLE FX3 FVARIABLE FY3

FVARIABLE FA FVARIABLE FB FVARIABLE FC

: B21 ( FX1 FY1 FX2 FY2 FX3 FY3 -> P S ) \ P=(A+B+C)/2 S=SQRT{P*(P-A) *(P-B) *(P-B)}

FY3 F! FX3 F! FY2 F! FX2 F! FY1 F! FX1 F! \ FX1 FY1 FX2 FY2 FX3 FY3 ->

FX1 F@ FY1 F@ FX2 F@ FY2 F@ B20 FDUP FA F! \ A

FX2 F@ FY2 F@ FX3 F@ FY3 F@ B20 FDUP FB F! \ A B

FX1 F@ FY1 F@ FX3 F@ FY3 F@ B20 FDUP FC F! \ A B C

F+ F+ FDUP \ A+B+C=P P

2E F/ \ P (A+B+C)/2=p

FDUP FA F@ F- \ P p p-A

FOVER FDUP FB F@ F- \ P p p-A p p-B

FSWAP FC F@ F- \ P p p-A p-B p-C

F* F* F* FSQRT \ P SQRT{p*(p-A)*(p-B)*(p-C)}=S

;

Строка №1 название слова с комментарием что она вычисляет.

Вторая – сохранение координат в соответствующих переменных.

С третьей по пятую – вычисление сторон треугольника с сохранением в переменных A, B, C. Здесь мы не высчитаем расстояния между точками (стороны треугольника), а пользуемся предыдущей задачей, в которой эта проблема решена, просто вызвав ее с параметрами задачи №21. В стековом комментарии написано, то что остается после работы строки (из-за нехватки места), присвоение переменных FA, FB, FC никак не обозначено.

Шестая строка вычисление периметра и его дублирование

Седьмая вычисление полупериметра.

С восьмой по десятую – вычисление сомножителей в формуле площади.

Одиннадцатая – вычисление самой площади.

Проверим работу слова на координатах: (1,1; 1,1) (6,1; 1,1) (6,1; 4,1). Это прямоугольный треугольник с катетами 3 и 5.

11E-1 11E-1 61E-1 11E-1 61E-1 41E-1 B21 F. F.

7.5000000 13.830952 Ok


рис 32

S=3*5/2=15/2=7.5. Гипотенуза равна sqrt(3^2+5^2)= sqrt(9+25)= sqrt(34)= 5,83095. P= 5,83095+3+5= 13,83095.

Что является истиной, то есть задачка запрограммирована корректно.

Если у вас будут проблемы и ошибки введите код в нижеприведенной последовательности.

S" lib\include\float2.f" INCLUDED

: B20 ( X1 Y1 X2 Y2-> R )

FROT F- FDUP F*

FSWAP FROT F- FDUP F*

F+ FSQRT ;

FVARIABLE FX1 FVARIABLE FY1 FVARIABLE FX2 FVARIABLE FY2 FVARIABLE FX3 FVARIABLE FY3

FVARIABLE FA FVARIABLE FB FVARIABLE FC

: B21 ( X1 Y1 X2 Y2 X3 Y3 -> P S ) FY3 F! FX3 F! FY2 F! FX2 F! FY1 F! FX1 F! FX1 F@ FY1 F@ FX2 F@ FY2 F@ B20 FDUP FA F! FX2 F@ FY2 F@ FX3 F@ FY3 F@ B20 FDUP FB F! FX1 F@ FY1 F@ FX3 F@ FY3 F@ B20 FDUP FC F! F+ F+ FDUP S" 2E" >FLOAT DROP F/ FDUP FA F@ F- FOVER FDUP FB F@ F- FSWAP FC F@ F- F* F* F* FSQRT ;

11E-1 11E-1 61E-1 11E-1 61E-1 41E-1 B21 F. F.

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

Пример 22. Довольно классическая задача по обмену содержимым между двумя переменными. В Форте создание переменных в данном случае даже не обязательна.

: B22 ( A B -> B A) SWAP ;

5 4 B22

Ok ( 4 5 )

Для вещественных аргументов.

: B22 ( A B -> B A) FSWAP ;


рис 33 без использования переменных

Теперь напишем с переменными:

VARIABLE A

VARIABLE B

: B22 ( -> ) \ обмен содержимым двух переменных A и B

A @ B @ A ! B ! ;

Как проверить работу?

15 A ! 50 B ! \ Сначала инициализируем переменные. A=15, B=50

Ok

B22 \ Вызов функции обмена переменных

Ok

A @ . B @ . \ Печатаем содержимое переменных после обмена

50 15 Ok


рис 34 с целочисленными переменными

Обмен вещественных переменных.

FVARIABLE FA

FVARIABLE FB

: B22 ( -> ) \ обмен содержимым для двух переменных A и B

FA F@ FB F@ FA F! FB F! ;

Проверим. Инициализируем переменные, вызовем слово и распечатаем результат. Все по стандартной схеме.

35E-1 FA F! \ A=3.5

Ok

77E-1 FB F! \ B=7.7

Ok

B22

Ok

FA F@ F. FB F@ F. \ Печать содержимого переменных после обмена

7.7000000 3.5000000 Ok \ A=7.7 B=3.5


рис 35 с вещественными переменными

У нас получилось четыре слова с одинаковыми именами, и каждое заменяет предыдущее, о чем нас предупреждает Форт система – SP-Forth сообщением «B22 isn't unique ()». Если вы собираетесь использовать несколько вариантов этих слов одновременно, то надо их называть разными именами. Например, как уже говорилось ранее, добавив «F» в начало слова, которые предназначены для работы с вещественными аргументами становится другим. Разные имена решают проблему и у вас становится больше инструментов в работе. Разумеется, в этом примере, первые два варианта (без использования переменных), в которых тело состоит всего лишь из одного оператора, в отдельные Форт-слова оформлять не обязательно. Просто помните о возможности таких манипуляций на стеке – это одна из сильных сторон Форта.

Пример 23. Обменять значения трех переменных A, B, C по следующей схеме: A -> B -> C -> A.

VARIABLE A VARIABLE B VARIABLE C

Если у вас все примеры в одном файле, то каждый раз объявлять переменные не надо. Добавьте только новую, в данном случае – это «VARIABLE C». Иначе будут сообщения от Форт системы

A isn't unique ()

B isn't unique ()

Это не критично, SP-Forth будет работать дальше, но, во-первых, будут созданы новые переменные с такими же именами, что просто будет бесполезно увеличивать расходы памяти, во-вторых, если вам нужно было предыдущее значение, то они уже не будут доступны по имени.


: B23 ( -> ) \ стековая нотация по прежнему пуста

A @ B @ C @ \ -> A B C

A ! C ! B ! \ A=C C=B B=A

;

1 A ! 2 B ! 3 C ! B23 A @ . B @ . C @ .

3 1 2 Ok

A=3, B=1, C=2.


рис 36

Для вещественного аргумента нужны соответствующие переменные.

FVARIABLE FA FVARIABLE FB FVARIABLE FC

: B23 ( -> ) \ стековая нотация по прежнему пуста

FA F@ FB F@ FC F@ \ -> A B C

FA F! FC F! FB F! \ C=A B=C A=B

;

1E FA F! 2E FB F! 3E FC F! B23 FA F@ F. FB F@ F. FC F@ F.

3.0000000 1.0000000 2.0000000 Ok \ FA=3 FB=1 FC=2

Инициализация и вывод слова «1E FA F! 2E FB F! 3E FC F! B23 FA F@ F. FB F@ F. FC F@ F.» получились не короче самого слова. Оформите в отдельное слово для обоих вариантов самостоятельно.


рис 37

Пример 24. Аналогичен предыдущему с перемещением содержимого по схеме: A -> C-> B -> A.

Переменные используем с предыдущего примера.

: B24 ( -> ) \ стековая нотация пуста

A @ B @ C @ \ -> A B C

B ! A ! C ! \ B=C A=B C=A

;

1 A ! 2 B ! 3 C ! \ инициализация A=1 B=2 C=3

Ok

B24 \ вызов нашей функции

Ok

A @ . B @ . C @ . \ A=2 B=3 C=1

2 3 1 Ok

Для вещественного аргумента.

: B24 ( -> ) \ стековая нотация пуста

FA F@ FB F@ FC F@ \ -> A B C

FB F! FA F! FC F! \ B=C A=B C=A

;

Проверим на аналогичных данных.

1E-1 FA F! 2E-1 FB F! 3E-1 FC F! B24 \ FA=0.1 FB=0.2 FC=0.3

FA F@ F. FB F@ F. FC F@ F. \ FA=0.2 FB=0.3 FC=0.1

0.2000000 0.3000000 0.1000000 Ok


рис 38


рис 39

Пример 25. Вычислить значение функции, если дан аргумент. Опустим целочисленный вариант, его можете написать самостоятельно.

: B25 ( X -> F[X] ) \ F(X)=3*X^6-6*x^2-7

F**2 \ X -> X^2

FDUP -6E F* \ X^2 -> X^2 -6*X^2

–7E F+ \ X^2 {-6*X^2} -> X^2 {-6*X^2-7}

FSWAP \ X^2 {-6*X^2-7} -> {-6*X^2-7} X^2

3E F** \ {-6*X^2-7} X^2 -> {-6*X^2-7} {X^2}^3=X^6

3E F* F+ \ {-6*X^2-7}+{3*X^6}

;

1E B25 F.

–10.000000 Ok \ F(1)=-10

1E-3 B25 F.

–7.0000060 Ok \ F(0.001)=– 7.0000060


рис 40

А вот при аргументе равным нулю выдает ошибку (возведение нуля в степень):

0E B25 F.

EXCEPTION! CODE:C0000090 ADDRESS:0055384E WORD:F**

USER DATA: 007005BC THREAD ID: 00002120 HANDLER: 0019EF98

STACK: (0) 5BF752DB 00328000 76F066DD 0019FFDC 74C30400 00328000 [74C30419]

RETURN STACK:

0019EF84 : 0056DC53 B25

…………………………………………………………

0019EFB4 : 0056BC66 (INIT)

END OF EXCEPTION REPORT

S" 0E >FLOAT DROP B25 F.

^ 0xC0000090L FLOAT_INVALID_OPERATION


рис 41

Но во второй раз у меня выдал другой ответ (разумеется уже некорректный):

0E B25 F.

infinity Ok

После этого лучше перезапустить систему и заново подключить библиотеки работы с вещественными числами или воспользоваться знакомым словом «FINIT», иначе он их не распознает:

1E B25 F.

1E B25 F.

^ -2003 WORD OR FILE NOT FOUND

0E B25 F.

0E B25 F.

^ -2003 WORD OR FILE NOT FOUND

1E-3 B25 F.

1E-3 B25 F.

^ -2003 WORD OR FILE NOT FOUND

После замены кода «F**2» на «FDUP F*» и «3E F**» на «FDUP FDUP F* F*» проблема исчезает.

: B25 ( X -> F[X] ) \ F(X)=3*X^6-6*x^2-7

FDUP F* \ X -> X^2

FDUP -6E F* \ X^2 -> X^2 -6*X^2

–7E F+ \ X^2 {-6*X^2} -> X^2 {-6*X^2-7}

FSWAP \ X^2 {-6*X^2-7} -> {-6*X^2-7} X^2

FDUP FDUP F* F* \ {-6*X^2-7} X^2 -> {-6*X^2-7} {X^2}^3=X^6

3E F* F+ \ {-6*X^2-7}+{3*X^6}

;

0E B25 F.

–7.0000000 Ok

Если ваша функция предполагает вычисление в нуле, не пользуйтесь функциями возведения в степень, используйте многократное умножение.

Пример 26. Брат близнец предыдущего. Разница в формуле. Так же рассмотрим только вещественный аргумент.

: B26 ( X -> F[X] ) \ F[X]=4*{X-3}^6-7*{X-3}^3+2