
Полная версия:
Решение задач по программированию на языке Форт (Forth). Версия 3
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
3E F- \ X -> X-3
3E F** \ X-3 -> (X-3)^3
FDUP -7E F* \ (X-3)^3 -> (X-3)^3 {-7*(X-3)^3}
FSWAP F**2 \ (X-3)^3 {-7*(X-3)^3} -> {-7*(X-3)^3} [(X-3)^3]^2
4E F* \ {-7*(X-3)^3} (X-3)^6 -> {-7*(X-3)^3} 4*(X-3)^6
2E F+ F+ \ {-7*(X-3)^3} 4*(X-3)^6 -> {-7*(X-3)^3}+4*(X-3)^6+2
;
4E B26 F.
–1.0000000 Ok
3E B26 F.
2.0000000 Ok
Здесь ошибки пи возведении нуля в степень не выдал, но при вводе кода «0E 3E F** F.» по-прежнему выдает ошибку. Будьте осторожны с возведением в степень, это опасная операция, вызывающая много ошибок.
Не привожу скана с тестом примера 26, разберите самостоятельно.
Пример 27. В Форте дополнительная переменная здесь и не понадобится. Для тех, кто любит все выполнять строго по инструкции – задание самостоятельно переписать код.
: B27 ( A -> A^2 A^4 A^8)
DUP * \ A -> A^2
DUP DUP * \ A^2 -> A^2 A^4
DUP DUP * \ A^2 A^4 -> A^2 A^4 A^8
;
Примеры работы слова:
2 B27
Ok ( 4 16 256 )
3 B27
Ok ( 9 81 6561 )
Без комментариев.

рис 42
С вещественным аргументом задача ничуть не сложнее. Заменяем все операторы на соответствующие, просто добавив «F».
: B27 ( A -> A^2 A^4 A^8 )
FDUP F* \ A -> A^2
FDUP FDUP F* \ A^2 -> A^2 A^4
FDUP FDUP F* \ A^2 A^4 -> A^2 A^4 A^8
;
2E B27 F. F. F.
256.00000 16.000000 4.0000000 Ok \ Порядок печати обратный
3E B27 F. F. F.
6561.0000 81.000000 9.0000000 Ok

рис 43
Пример 28. Похож на предыдущую задачу и чуть посложнее.
: B28 ( A -> A^2 A^3 A^5 A^10 A^15 )
DUP DUP * \ A -> A A^2
SWAP OVER * \ A A^2 -> A^2 A^3
OVER OVER * \ A^2 A^3 -> A^2 A^3 A^5
DUP DUP * \ A^2 A^3 A^5 -> A^2 A^3 A^5 A^10
OVER OVER * \ A^2 A^3 A^5 A^10 -> A^2 A^3 A^5 A^10 A^15
;
2 B28
Ok ( 4 8 32 1024 32768 )
3 B28
Ok ( 9 27 243 59049 14348907 )
Не забывайте, что степенная функция растет очень быстро и при большом основании быстро произойдет переполнение, в результате ответ будет некорректным. Так, например, при A=10, уже 10-ая степень вычисляется неправильно.
10 B28
Ok ( 100 1000 100000 1410065408 2764472320(-1530494976) )
Для вещественного аргумента.
: B28 ( A -> A^2 A^3 A^5 A^10 A^15)
FDUP FDUP F* \ A -> A A^2
FSWAP FOVER F* \ A A^2 -> A^2 A^3
FOVER FOVER F* \ A^2 A^3 -> A^2 A^3 A^5
FDUP FDUP F* \ A^2 A^3 A^5 -> A^2 A^3 A^5 A^10
FOVER FOVER F* \ A^2 A^3 A^5 A^10 -> A^2 A^3 A^5 A^10 A^15
;

рис 44

рис 45
Тесты с вещественным параметром.
2E B28 F. F. F. F. F.
32768.000 1024.0000 32.000000 8.0000000 4.0000000 Ok \ опять обратный порядок при печати
3E B28 F. F. F. F. F.
14348907. 59049.000 243.00000 27.000000 9.0000000 Ok
Очевидно слова работает корректно.
Пример 29. Перевести градусы в радианы.
Целочисленный вариант будет в 100 раз больше, поэтому его код не приводится. При необходимости можно его получить из кода для вещественного аргумента. Также можете воспользоваться словом «.2»
: B29 ( A{DEG} -> X{RAD} ) \ X=A*Pi/180
314E-2 F* \ A -> 3.14*A
180E F/ \ 3.14*A -> 3.14*A/180
;
Нижеприведенные тесты корректны.
90E B29 F.
1.5700000 Ok
360E B29 F.
6.2800000 Ok
Для повышения точности, самостоятельно перепишите слово «B29» используя слово «FPI».

рис 46
Пример 30. Обратная к предыдущему задача перевода из радиан в градусы.
: B30 ( A{RAD} -> X{DEG} ) \ 180*A/Pi
180E F* \ A -> 180*A
314E-2 F/ \ 180*A -> 180*A/Pi
;
Тесты слова B30.
314E-2 B30 F.
180.00000 Ok
628E-2 B30 F.
360.00000 Ok

рис 47
Как и в предыдущем случае, перепишите для увеличения точности.
Если вы планируете использовать последние два слова в своей работе, то можно их назвать по практичнее и добавить в свой файл Форт-расширения (или в свою математическую библиотеку).
Например, RAD>DEG и DEG>RAD (знак «>» означает перевести, перенести в зависимости от контекста использования).
Пример содержания такого файла:
\ Подключение библиотеки для работы с вещественными числами
S" lib\include\float2.f" INCLUDED
VARIABLE A VARIABLE B VARIABLE C \ Часто используемые переменные
FVARIABLE FA FVARIABLE FB FVARIABLE FC
: DEG>RAD ( A{DEG} -> X{RAD} ) \ X=A*Pi/180 – градусы в радианы
314E-2 F* \ A -> 3.14*A
180E F/ \ 3.14*A -> 3.14*A/180
;
: RAD>DEG ( A{RAD} -> X{DEG} ) \ 180*A/Pi – радианы в градусы
180E F* \ A -> 180*A
314E-2 F/ \ 180*A -> 180*A/Pi
;
Назовите файл как вам нравится, но обязательно с расширением «.F», тогда его можно будет запустить и он откроется в SP-Forth, при условии, что он у вас установлен. Тогда вам не придется каждый раз выполнять рутинные задачи, которые вы включите в этот файл.
Чтобы упростить интерфейс взаимодействия с написанными словами, например, вывод результатов расчета для слов со множеством выходных данных, можно применить уже описанную выше методику.
Рассмотрим пример №28.
2E B28 F. F. F. F. F.
Здесь «B28 F. F. F. F. F.» заменяем на слово
: B28. ( A^2 A^3 A^5 A^10 A^15 -> ) B28 F. F. F. F. F. ;
Такой вариант предпочтительный не только из-за упрощения, но и исходя из того, что вы со временем забудете, как работает слово, а разбираться в работе слове каждый раз не разумно, да и зачем перегружать мозг бесполезными мелочами? Оператор «.» – точка в Форте всегда связана с печатью на экран, поэтому «Name.» – логично означает печать результатов слова «Name». Только не забудьте написать соответствующее слово перед ее выполнением, автоматически слова в Форте не пишутся. Так же можно включать словесное описание результатов, например,
: B28. ( A^2 A^3 A^5 A^10 A^15 -> ) B28
.” A^15= “ F. CR \ CR – это оператор перевода на новую строку
.” A^10= “ F. CR
.” A^5= “ F. CR
.” A^3= “ F. CR
.” A^2= “ F. CR
;
Окончательно вызов слова B28 будет выглядеть, с учетом упрощения, так:
2E B28.
Так мы разделяем алгоритм работы слова с его примитивным интерфейсом вывода результатов на экран. В таком случае при необходимости что-то доработать, одно не помешает другому и, разумеется, код становится более лаконичным и понятным. Оригинал «B28» можно использовать в других словах, библиотеках, и это никак не помешает по-прежнему пользоваться примером 28. Так же при решении сложной задачи, можно писать аналогичные промежуточные слова «Name.» для отладки и контроля промежуточного состояния сложной системы слов, когда не понятно на каком этапе возникает ошибка.

рис 48
BEGIN 31-40
Пример 31. Перевести температуру в Фаренгейтах в градусы Цельсия. Сперва для целых значений температуры.
: B31 ( TF-> TC ) \ TC=(TF-32)*5/9
32 – 5 * 9 /
;
32 B31 \ 32 град Фаренгейта = 0 град Цельсия, 32-32=0, 0*5/9=0
Ok ( 0 )
35 B31 \ 35 град Фаренгейта = 1 град Цельсия (35-32)=3, 3*5=15, 15/9=1 – целая часть
Ok ( 0 1 )
40 B31 \ 40 град Фаренгейта = 4 град Цельсия (40-32)=8, 8*5=40, 40/9=4 – целая часть
Ok ( 0 1 4 )

рис 49
С незначительными изменениями мы сможем переписать код для вещественных значений температуры.
: B31 ( TF-> TC ) \ TC=(TF-32)*5/9
32E F-
5E F* 9E F/
;
32E B31 F. \ как и в первом варианте, только результат в вещественном формате
0.0000000 Ok
321E-1 B31 F.
0.0555555 Ok

рис 50
Пример 32. Обратная к предыдущему примеру задача. Перевести температуру из Цельсия в Фаренгейты.
: B32 ( TC -> TF ) \ TF= TC*9/5+32
9 * 5 / 32 + ;
0 B32 \ 0 град Цельсия = 32 град Фаренгейта
Ok ( 32 )
–18 B32
Ok ( 32 0 ) \ -18 град Цельсия = 0 град Фаренгейта

рис 51
Для вещественного аргумента.
: B32 ( TC -> TF ) \ TF= TC*9/5+32
9E F* 5E F/ 32E F+ ;
0E B32 F. \ 0 град Цельсия = 32 град Фаренгейта
32.000000 Ok
–18E B32 F. \ -18 град Цельсия = -0,4 град Фаренгейта
–0.4000000 Ok

рис 52
Ноль градусов по Цельсию по-прежнему 32 градусов Фаренгейта, единственное отличие – результат вещественное число, а вот при T=-18 остаток уже не отбрасывается, как в первом случае, и ответ получается точный.
Пример 33. Детская задача. Цена 1 кг конфет обозначим через C1, а Y кг соответственно CY, тогда легко вычислить C1=A/X и CY=C1*Y, а дано X кг за A рублей и количество Y кг, цену которого нужно вычислить.
: B33 ( X A Y -> C1 CY ) \ C1=A/X CY=C1*Y
SWAP ROT / \ X A Y -> Y A/X=C1
SWAP OVER * \ Y C1 -> C1 Y*C1= CY
;
3 9 10 B33 \ 3 кг стоит 9 р, т. е. 3р за 1 кг, а 10 кг будут стоить 3*10=30 р
Ok ( 3 30 )
Вы можете самостоятельно потренироваться на современных ценах различных товаров.
А теперь для дробных цен.
: B33 ( X A Y -> C1 CY ) \ C1=A/X CY=C1*Y
FSWAP FROT F/ \ X A Y -> Y A/X=C1
FSWAP FOVER F* \ Y C1 -> C1 Y*C1= CY
;
3E 9E 10E B33 F. F.
30.000000 3.0000000 Ok

рис 53
Проверили на тех же данных. И снова не забываем об обратном порядке при печати со стека, не важно с какого (целочисленного или вещественного). Чтобы в начале вывести цену за 1 кг, можно использовать слово FSWAP перед «F.» или переписать строчку
FSWAP FOVER F* \ Y C1 -> C1 Y*C1= CY
таким образом
FDUP F. F* \ Y C1 -> Y*C1= CY
Но в этом случае код не универсален, а значит менее предпочтителен. Желательно вычисление и печать разграничить, чтобы можно было, написанную функцию использовать в различных местах и ситуациях, а не «изобретать велосипед» каждый раз.
Пример 34. Продолжение детских задачек.
: B34 ( X A Y B -> CX CY CX/CY ) \ CX=A/X CY=B/Y CX/CY
SWAP / \ X A Y B -> X A B/Y=CY
SWAP ROT / \ X A CY -> CY A/X=CX
SWAP 2DUP / \ CY CX -> CX CY CX/CY
;
5 30 5 15 B34
Ok ( 6 3 2 )
Цена шоколадных конфет равна 30/5= 6 р/кг, ирисок 15/5=3 р/кг, и соответственно шоколадные конфеты дороже ирисок в 6/3=2 раза. Перепишем для вещественных аргументов, чтобы не терять точность для «неудобных данных».
: B34 ( X A Y B -> CX CY CX/CY ) \ CX=A/X CY=B/Y CX/CY
FSWAP F/ \ X A Y B -> X A B/Y=CY
FSWAP FROT F/ \ X A CY -> CY A/X=CX
FSWAP FOVER FOVER F/ \ CY CX -> CX CY CX/CY
;
5E 30E 5E 15E B34 F. F. F.
2.0000000 3.0000000 6.0000000 Ok

рис 54



