ISBN :
Возрастное ограничение : 12
Дата обновления : 14.12.2023
ROT ROT ( A*B=S A B ) \ оператор ROT вытаскивает 3-ий от вершины параметр на вершину
\ применив его два раза на вершине мы получаем A B и вычисленный под ним Площадь
+ 2* ; \ складываем A и B, и умножив на 2, оператором 2*, получаем периметр
Слово «2*» делает тоже самое что и два слова «2 *», только короче и проще.
В итоге на стеке мы получаем Площадь и Периметр. Чтобы напечатать результаты на экран из примеров нужно просто ввести точку с клавиатуры «.» и затем нажать «Enter». Сначала напечатается вершина, т. е. периметр, в данном примере, затем повторив действия площадь. Чтобы изменить порядок печати, можно набрать слово SWAP, который меняет местами 2 числа на вершине стека ( A B -> B A), т.е., например чтобы вычислить площадь и периметр прямоугольника со сторонами 1 и 2 введём следующее:
1 2 B3 SWAP . .
2 6 Ok
Площадь равна 1*2=2, а периметр равен 2*(1+2)=6. Слово работает корректно и вычисляются площадь и периметр соответственно стековой нотации, а выводятся по условию задачи.
Пример 4. Нужно вычислить длину круга зная его диаметр:
: B4 ( D -> L ) 314 * ; \ L=Pi*D*100
Ответ буде в 100 раз больше для целочисленных данных, таким образом избавимся от дробной части. Перепишем код, чтобы можно было работать с вещественными числами. Для этого в SP-Forth нужно подключить соответствующие библиотеки. Скопируйте и вставьте следующие две строчки:
S" lib\include\float.f" INCLUDED
S" lib\include\float2.f" INCLUDED
Но можно только вторую строчку.
Теперь чтобы ввести вещественное число, скажем 0,5, нужно набрать на клавиатуре следующее:
5E-1
До E – это мантисса (число), после экспонента (степень). Мантисса и экспонента могут быть как положительными (знак не требуется), так и отрицательными (в данном случае степень -1, что значит 10 в минус первой степени).
После ввода, вещественное число размещается на соответствующем ей стеке, поэтому мы не видим его после вывода слова Ok в скобках, так как это другой стек для целых чисел. Чтобы его увидеть нужно ввести «F.». Итак, чтобы проверить, что всё работает как надо, введём код:
5E-1 F.
В ответ увидим:
0.5000000 Ok
Слово «F.», аналогично, как и «.» выводит число на экран, только не с целочисленного стека, а с вещественного.
Теперь мы можем переписать пример 4 для вещественных аргументов:
: B4 ( D -> L ) \ L=Pi*D
314E-2 F* ;
Посчитаем длину окружности диаметром 0,5, набрав следующее:
5E-1 B4 F. \ вызываем слово, которое считает длину и «F.» печатает ответ
1.5700000 Ok
Переделаем таким же образом первые 3 примера для случая с вещественными аргументами, сделав их более универсальными.
Пример 1:
: B1 ( A -> P ) 4E F* ; \ P=4*A
Знак «*» заменяется на «F*», четверка вводится как вещественное число (операция «F*», в отличие от «*» производит операцию над вещественными числами на вещественном стеке). Теперь проверим, посчитаем периметр квадрата со стороной 0,5:
5E-1 B1 F.
2.0000000 Ok
Ответ 2 (0,5*4=2) что является правдой.
Данный пример, так же можно преобразовать, написав в стиле:
: B1 ( A -> P ) \ P=4*A
4E F*
;
Но он настолько маленький и примитивный, что едва ли это необходимо, проще и лаконичней всё оставить на одной строчке. В более сложных и больших примерах код нужно писать структурированным, понятным и разумеется в едином стиле.
Пример 2:
: B2 ( A -> S ) FDUP F* ; \ S=A^2
Опять DUP превращается в FDUP, умножение как в первом случае. Проверим работу слова. Посчитаем площадь квадрата со стороной 0,5:
5E-1 B2 F.
0.2500000 Ok \ 0,5*0,5 = 0,25
Пример 3:
: B3 ( A B -> S P ) \ ( S=A*B P=2*(A+B) )
FOVER FOVER ( A B -> A B A B )
\ Слово FOVER, дублирует слово под вершиной стека на ее вершину т.е. ( A B -> A B A )
\ Повторив его 2 раза получим ( A B -> A B A B )
F* F. ( A B A B -> A B A*B=S )
\ Площадь вычислен – это просто произведение сторон
F+ 2E F* F. ; \ складываем A и B, и умножив на 2, оператором F*, получаем периметр
Проверим работу слова B3:
2E-1 3E-1 B3
0.0600000 1.0000000 Ok
Как можете увидеть ниже всё работает верно:
S = 0,2*0,3=0,06
P=2*(0,2+0,3)=2*0,5=1
0,2 и 0,3 можно вводить и в следующем виде: 0.2E и 0.3E. Самостоятельно можете убедиться, что слово «F.» выведет на экран тоже самое значение.
Универсальный вариант того же примера, если вы не хотите сразу печатать результаты обработки в слове:
: B3 ( A B -> S P ) \ ( S=A*B P=2*(A+B) )
FOVER FOVER ( A B -> A B A B )
F* ( A B A B -> A B A*B=S )
\ Площадь вычислен – это просто произведение сторон
FROT FROT ( A B A*B=S -> A*B=S A B )
F+ 2E F* ; \ складываем A и B, и умножив на 2, оператором F*, получаем периметр
Проверим. Посчитаем площадь и периметр прямоугольника со сторонами 0,2 и 0,3:
2E-1 3E-1 B3
Ok
F. F.
1.0000000 0.0600000 Ok
Сначала выводит периметр затем площадь, чтобы изменить порядок как указано в стековой нотации нужно набрать команду FSWAP перед печатью результатов, то есть:
2E-1 3E-1 B3 FSWAP F. F.
0.0600000 1.0000000 Ok
Результаты по-прежнему верны.
Вы можете спросить зачем такие сложности? Код становится универсальным, мы отделяем вычисляемую часть от метода вывода данных на экран, его можно включать в свои библиотеки, и использовать в других задачах как отдельную функцию.
Как вы уже могли заметить одно замечательное свойство Форта – его слова-функции не только принимают любое количество аргументов, но также оставляют на стеке желаемое число результатов, не каждый ЯП может этим похвастаться.
Пример 5. Здесь вычисляется объем куба и площадь его боковой поверхности. Вначале приведем работу с целочисленным аргументом.
: B5 ( A -> V S ) DUP 2DUP * * SWAP DUP * 6 * ; \ V=A^3 S=6*A^2
Поясним код:
DUP 2DUP ( A -> A A A A )
2DUP, в отличие от DUP дублирует сразу 2 верхних элемента
* * ( A A A A -> A A*A*A=A^3 )
двойное применение операции умножения дает в результате куб
SWAP ( A A^3 -> A^3 A )
SWAP просто поменял местами два верхних элемента на стеке
DUP * (A^3 A -> A^3 A*A )
возвели в квадрат число на вершине стека
6 * (A^3 A*A -> A^3 6*A^2)
и умножили его на 6, число сторон куба
Вызовем написанное слово с параметром 15 (сторона куба):
15 B5
Ok ( 3375 1350 )
3375=15*15*15 и 1350=6*15*15, все верно, слово работает корректно.
То же самое в вещественных числах:
: B5 ( A -> V S ) \ V=A^3 S=6*A^2
FDUP FDUP FDUP ( A -> A A A A ) \ 2FDUP SP-Forth не понимает
F* F* ( A A A A -> A A*A*A=A^3 )
FSWAP ( A A^3 -> A^3 A )
Все книги на сайте предоставены для ознакомления и защищены авторским правом