Читать книгу Язык программирования Форт (Forth). Решение задач по программированию. Версия 2. (Arsen Gonian) онлайн бесплатно на Bookz (2-ая страница книги)
bannerbanner
Язык программирования Форт (Forth). Решение задач по программированию. Версия 2.
Язык программирования Форт (Forth). Решение задач по программированию. Версия 2.
Оценить:
Язык программирования Форт (Forth). Решение задач по программированию. Версия 2.

3

Полная версия:

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

ROT ROT 2DUP *            \ (+) A^2 B^2 (-) -> (+) (-) A^2 B^2 (A^2*B^2)

ROT ROT /                  \ (+) (-) A^2 B^2 (*) -> (+) (-) (*) (A^2/B^2 )

;

Протестируем на числах 4 и 2.

4 2 B10

Ok ( 20 12 64 4 )

Всё корректно, проверяйте самостоятельно. В комментариях я сократил сумму, разность и произведение квадратов до соответствующих операций в скобках. Специально подобраны такие числа, чтобы результат деления был целочисленным, но это не обязательно – код для вещественных аргументов избавит нас от таких неудобств:

: B10 ( A B -> A^2+B^2 A^2-B^2 A^2*B^2 A^2/B^2 )

FSWAP FDUP F*      \ A B -> B A^2

FSWAP FDUP F*      \ B A^2 -> A^2 B^2

FOVER FOVER F+      \ A^2 B^2 -> A^2 B^2 (A^2+B^2)

FROT FROT FOVER FOVER F-      \ A^2 B^2 (A^2+B^2) -> (A^2+B^2) A^2 B^2 (A^2-B^2)

FROT FROT FOVER FOVER F*      \ (+) A^2 B^2 (-) -> (+) (-) A^2 B^2 (A^2*B^2)

FROT FROT F/                  \ (+) (-) A^2 B^2 (*) -> (+) (-) (*) (A^2/B^2)

;

Тест примера 10:

1E-1 2E-1 B10 F. F. F. F.

0.2500000 0.0004000 -0.0300000 0.0500000 Ok

Не забываем, что оператор F. Печатает число с вершины стека, поэтому сначала напечатается частное, затем произведение, после чего разность и в конце сумма.

0,25 = 0,01/0,04; 0,0004 = 0,01*0,04; -0,03 = 0,01-0,04; 0,05 = 0,01+0,04.

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


BEGIN 11-20

Пример 11. Отличается от 10-ого примера незначительными поправками. Просто заменяем квадрат на модуль: код «DUP *» на «ABS».

: B11 ( A B -> {|A|+|B|} {|A|-|B|} {|A|*|B|} {|A|/|B|} )

SWAP ABS SWAP ABS      \ A B ->|A| |B|

2DUP +                  \ |A| |B|-> |A| |B| (|A|+|B|)

ROT ROT 2DUP –      \ |A| |B| (|A|+|B|) -> (|A|+|B|) |A| |B| (|A|-|B|)

ROT ROT 2DUP *      \ (+) |A| |B| (-) -> (+) (-) |A| |B| (|A|*|B|)

ROT ROT /            \ (+) (-) |A| |B| (*)-> (+) (-) (*) (|A|/|B|)

;

В случае для вещественных аргументов:

: B11 ( A B -> {|A|+|B|} {|A|-|B|} {|A|*|B|} {|A|/|B|} )

FSWAP FABS                  \ A B -> B |A|

FSWAP FABS                  \ B |A| -> |A| |B|

FOVER FOVER F+            \ |A| |B|-> |A| |B| (|A|+|B|)

FROT FROT FOVER FOVER F-      \ |A| |B| (|A|+|B|) -> (|A|+|B|) |A| |B| (|A|-|B|)

FROT FROT FOVER FOVER F*      \ (+) |A| |B| (-) -> (+) (-) |A| |B| (|A|*|B|)

FROT FROT F/                  \ (+) (-) |A| |B| (*)-> (+) (-) (*) (|A|/|B|)

;

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

Тест на корректность работы написанных слов произведите самостоятельно.

Пример 12. Вычислить гипотенузу и периметр прямоугольного треугольника по его катетам. Так как мы имеем дело с квадратным корнем, сразу приведем код для случая вещественного аргумента.

: B12 ( A B -> C P )      \ C=Квадратный_Корень(A^2+B^2) P=A+B+C

FOVER FDUP F*            \ A B -> A B A^2

FOVER FDUP F*            \ A B A^2 -> A B A^2 B^2

F+ FSQRT            \ A B A^2 B^2 -> A B Квадратный_Корень(A^2+B^2)=C

FROT FROT F+            \ A B C -> C A+B

FOVER F+            \ C A+B -> C A+B+C=P

;

Проверим на прямоугольном треугольнике с катетами 3 и 5:

3E 4E B12 F. F.                  \ вызываем нашу подпрограмму и печатаем результат

12.000000 5.0000000 Ok

3^2+4^2=25. Квадратный корень из 25=5. 5+3+4=12– что является истиной. В данном случае специально подобрана Пифагорова тройка, для простоты проверки. Проверим общий случай:

3E 5E B12 F. F.

13.830952 5.8309519 Ok

Можете самостоятельно проверить истинность теста.

Пример 13. Найти площади двух кругов (с общим центром) и кольца между ними. Даны радиусы R1 и R2, причем R1 > R2. Как и ранее сперва напишем слово для целочисленных чисел. Если не совсем понятно почему не написать сразу универсальный вариант для вещественных данных, то поясняю: отладка в этом случае наиболее проста для сложных слов и для начинающих программистов, так как все данные на стеке видны сразу после их ввода, то удается проверить и понять работу кода вводя команду за командой. Этого преимущества лишены операторы для работы с вещественными числами. После написания слова с целыми аргументами не сложно перевести его код для работы с вещественными и получить результат того же типа.

: B13 ( R1 R2 -> S1 S2 S3)            \ S1=Pi*R1^2 S2= Pi*R2^2 S3=S1-S2

SWAP DUP * 314 *      \ R1 R2 -> R2 (Pi*R1^2)=S1

SWAP DUP * 314 *      \ R2 S1 -> S1 (Pi*R2^2)=S2

2DUP –                  \ S1 S2 -> S1 S2 (S1-S2)=S3

;

Запустим наше слово на примере двух кругов с радиусами 25 и 15 соответственно.

25 15 B13

Ok ( 196250 70650 125600 )

Выше приведен вариант кода с целочисленными аргументами, причем все 3 площади больше в 100 раз из-за того, что мы приняли Пи равным 314. Перепишем пример для случая вещественных аргументов.

: B13 ( R1 R2 -> S1 S2 S3)            \ S1=Pi*R1^2 S2= Pi*R2^2 S3=S1-S2

FSWAP FDUP F* 314E-2 F*      \ R1 R2 -> R2 (Pi*R1^2)=S1

FSWAP FDUP F* 314E-2 F*      \ R2 (Pi*R1^2)=S1 -> (Pi*R1^2)=S1 (Pi*R2^2)=S2

FOVER FOVER F-                        \ S1 S2 -> S1 S2 (S1-S2)=S3

;

Тестирование примера 13:

25E-1 15E-1 B13 F. F. F.

12.560000 7.0650000 19.625000 Ok

S1 = 19,625 = 3.14*2.5^2; S2 = 7,065 = 3.14*1.5^2; S3=S1-S2=12,56=19,625-7,065. Тестирование прошло успешно. Не забываем про обратный порядок печати со стека. Написанное слово работает правильно, соответственно стековой нотации. Если вам необходим другой порядок вывода, то можете самостоятельно скорректировать слово, добавив код после вызова «B13» и до вывода «F. F. F.».

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

: B14 ( L -> R S )      \ R=L/(2*Pi) S=Pi*R^2

628e-2 F/                  \ L -> R=L/6.28 где 6,28=2*Pi=D

FDUP FDUP F* 314e-2 F*      \ R -> R Pi*R^2

;

Посчитаем R и S для L=25,37

2537E-2 B14 F. F.

51.244976 4.0398089 Ok

R=25.37/6.28= 4,0398 и S=3,14* 4,0398^2= 51,244. Тест прошел успешно.

Пример 15. Зная площадь круга, вычислить его диаметр и длину.

: B15 ( S -> D L )                  \ D=Квадратный_Корень(4*S/Pi) L=Pi*D

4E F*                  \ S -> 4*S

314E-2 F/            \ 4*S -> 4*S/Pi

FSQRT                  \ 4*S/Pi -> Квадратный_Корень(4*S/Pi)=D

FDUP 314E-2 F*      \ D -> D D*Pi=L

;

Посчитаем диаметр и длину круга площадью равной 12,345.

12345E-3 B15 F. F.

12.452036 3.9656166 Ok

Квадратный корень из (12,345*4/3.14) равно 3,965616, а 3,965616*3,14=12,4520, то ест ь ИСТИНА. Пример довольно простой и нет других причин писать код для целочисленного варианта аргументов. В случае необходимости несложно самостоятельно решить эту задачу.

Пример 16. Вычислим расстояние между двумя точками на числовой оси, зная координаты.

: B16 ( X1 X2 -> |X1-X2| )

– ABS      \ X1 X2 -> |X1-X2|

;

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

: B16 ( X1 X2 -> |X1-X2| )

F- FABS      \ X1 X2 -> |X1-X2|

;

31E-1 -12E1 B16 F.

123.10000 Ok                  \ |3.1-(-120)|=123.1

Пример 17. По трем координатам на числовой оси (X1, X2, X3) вычислить следующие расстояния: |x1-x3|, |x2-x3| и их сумму. Сперва для целых чисел.

: B17 ( X1 X2 X3 -> |x1-x3| |x2-x3| {|x1-x3|+|x2-x3|} )

SWAP OVER            \ X1 X2 X3 -> X1 X3 X2 X3

– ABS                  \ X1 X3 X2 X3 -> X1 X3 |X2-X3|

ROT ROT – ABS SWAP      \ X1 X3 |X2-X3| -> | X1-X3| |X2-X3|

2DUP +                  \ | X1-X3| |X2-X3|-> | X1-X3| |X2-X3| (| X1-X3|+|X2-X3|)

;

Для вещественных.

: B17 ( X1 X2 X3 -> |x1-x3| |x2-x3| {|x1-x3|+|x2-x3|} )

FSWAP FOVER                  \ X1 X2 X3 -> X1 X3 X2 X3

F- FABS                        \ X1 X3 X2 X3 -> X1 X3 |X2-X3|

FROT FROT F– FABS FSWAP      \ X1 X3 |X2-X3| -> | X1-X3| |X2-X3|

FOVER FOVER F+            \ | X1-X3| |X2-X3|-> | X1-X3| |X2-X3| (| X1-X3|+|X2-X3|)

;

Тест на координатах

–1E1 1E-1 3E2 B17 F. F. F.

609.90000 299.90000 310.00000 Ok

|X1-X3|=|-10-300|=310; |X2-X3|=|0.1-300|=299.9; (|X1-X3|+|X2-X3|)=310+299.9=609.9.

Пример 18. Схож с предыдущей задачей. Сумма заменяется произведением.

: B18 ( X1 X2 X3 -> {|x1-x3|*|x2-x3|} )

SWAP OVER            \ X1 X2 X3 -> X1 X3 X2 X3

– ABS                  \ X1 X3 X2 X3 -> X1 X3 |X2-X3|

ROT ROT – ABS *      \ X1 X3 |X2-X3| -> {|x1-x3|*|x2-x3|}

;

–5 2 7 B18

Ok ( 60 )

|-5-7|*|2-7|= 12*5=60

Для вещественных чисел.

: B18 ( X1 X2 X3 -> {|x1-x3|*|x2-x3|} )

FSWAP FOVER            \ X1 X2 X3 -> X1 X3 X2 X3

F- FABS                  \ X1 X3 X2 X3 -> X1 X3 |X2-X3|

FROT FROT F– FABS F*      \ X1 X3 |X2-X3| -> {|x1-x3|*|x2-x3|}

;

–1E1 2E-1 23E1 B18 F.

55152.000 Ok

|-10-230|*|0.2-230|=240*229.8=55152

Пример 19. По координатам противоположенных вершин прямоугольника вычислить его периметр и площадь, стороны параллельны координатным осям.

: B19 ( X1 Y1 X2 Y2 -> P S )      \ P=2*[A+B] S=A*B

ROT – ABS            \ X1 Y1 X2 Y2 -> X1 X2 |Y2-Y1|

SWAP ROT – ABS      \ X1 X2 |Y2-Y1| -> |Y2-Y1|=A |X2-X1|=B

2DUP + 2*            \ A B -> A B 2*(A+B)=P

ROT ROT *            \ A B P -> P A*B=S

;

1 3 7 8 B19 . .

30 22 Ok

A=|1-7|=6 B=|3-8|=5. P=2*(A+B)=2*(6+5)=22. S=A*B=6*5=30.

Вариант с вещественными аргументами не сильно отличается от целочисленного.

: B19 ( X1 Y1 X2 Y2 -> P S )            \ P=2*[A+B] S=A*B

FROT F- FABS                  \ X1 Y1 X2 Y2 -> X1 X2 |Y2-Y1|

FSWAP FROT F– FABS            \ X1 X2 |Y2-Y1| -> |Y2-Y1|=A |X2-X1|=B

FOVER FOVER F+ 2E F*            \ A B -> A B 2*(A+B)=P

FROT FROT F*                  \ A B P -> P A*B=S

;

11E-1 15E-1 73E-1 62E-1 B19 F. F.

29.140000 21.800000 Ok

A=|1.5-6.2|=4.7; B=|1.1-7.3|=6.2; P=2*(4.7+6.2)= 21,8; S=A*B=4.7*6.2= 29,14.

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

: B20 ( X1 Y1 X2 Y2-> R )                  \ R= Квадратный_Корень((X2-X1)^2+(Y2-Y1)^2)

FROT F- FDUP F*            \ X1 Y1 X2 Y2-> X1 X2 (Y2-Y1)^2

FSWAP FROT F- FDUP F*      \ X1 X2 (Y2-Y1)^2 -> (Y2-Y1)^2 (X2-X1)^2

F+ FSQRT                  \ (Y2-Y1)^2 (X2-X1)^2 -> R

;

11E-1 15E-1 73E-1 62E-1 B20 F.

7.7801028 Ok

A=|1.5-6.2|=4.7; B=|1.1-7.3|=6.2; R= Квадратный_Корень(A^2+B^2)= Квадратный_Корень(22.09+ 38,44)= 7,7801.


BEGIN 21-30

Перед решением очередного примера рассмотрим, как объявляются и используются переменные в SP-Forth. Так как операции с большим количеством данных на стеке становится крайне затруднительным, нам они пригодятся. Для этого используется зарезервированные слова VARIABLE и FVARIABLE. Первое для целых чисел, второе для вещественных. Если кто-то не знает, что такое переменная, то это просто участок памяти, в которое записывается значение (число для целых переменных, текст для строковых или их комбинация для структур), считывается или изменяется. На самом деле любые данные, неважно что: простые переменные, структуры или даже файлы, все они кодируется исключительно числами, причем в двоичном формате (нуликами и единицами).

Создадим две переменные

FVARIABLE FVAR      \ FVAR переменная вещественного типа

VARIABLE VAR            \ VAR переменная целого типа

Теперь инициализируем эти переменные, то есть присвоим начальное значение.

1234E-2 FVAR F!

Ok

4552249 VAR !

Ok

Код «1234E-2» нам уже знаком, он просто переносит число «1234E-2» в вещественный стек, FVAR оставляет адрес вещественной переменной с этим именем, и в итоге «F!» – записывает значение в адрес. Целочисленное присвоение выглядит по проще, но суть та же. Сначала число идет в стек. Слово VAR также оставляет адрес целочисленной переменной на стеке. А записывает значение по адресу оператор «!» – восклицательный знак. А считывает – «F@» и «@» соответственно. Теперь считаем и выведем на экран значения созданных и инициализированных выше переменных.

VAR @ .

4552249 Ok

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

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 ( X1 Y1 X2 Y2 X3 Y3 -> 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.

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

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

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

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

Проверим работу слова на координатах: (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

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 ;

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

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

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

FVARIABLE FA

FVARIABLE FB

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

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

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

Конец ознакомительного фрагмента.

Текст предоставлен ООО «Литрес».

Прочитайте эту книгу целиком, купив полную легальную версию на Литрес.

Безопасно оплатить книгу можно банковской картой Visa, MasterCard, Maestro, со счета мобильного телефона, с платежного терминала, в салоне МТС или Связной, через PayPal, WebMoney, Яндекс.Деньги, QIWI Кошелек, бонусными картами или другим удобным Вам способом.

Вы ознакомились с фрагментом книги.

Для бесплатного чтения открыта только часть текста.

Приобретайте полный текст книги у нашего партнера:


Полная версия книги

Всего 10 форматов

bannerbanner