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

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

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

Язык: Русский
Год издания: 2023
Добавлена:
Настройки чтения
Размер шрифта
Высота строк
Поля
На страницу:
3 из 4

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

Пример 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

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

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

Но во второй раз у меня выдал другой ответ:

0E B25 F.

infinity Ok

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

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.» по-прежнему выдает ошибку. Будьте осторожны при возведении в степень, это опасная операция, вызывающая много ошибок.

Пример 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 )

Без комментариев.

С вещественным аргументом задача ничуть не сложнее. Заменяем все операторы на соответствующие, просто добавив «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

Пример 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

;

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 раз больше, поэтому его код не приводится. При необходимости можно его получить из кода для вещественного аргумента.

: 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».

Пример 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

Как и в предыдущем случае, перепишите для увеличения точности.

Небольшие хитрости для оптимизации работы с системой программирования SP-forth.

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

Например, 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

;

: MIDDLE_ARITHMETIC ( A B -> [A+B]/2 )      \ среднее арифметическое

F+ 2E F/ ;

: MIDDLE_GEOMETRIC ( A B -> SQRT[A*B] )      \ среднее геометрическое

F* FSQRT ;

: R2D ( 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

;

Назовите файл как вам нравится, но обязательно с расширением «.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^2= “ F. CR      \ CR – это оператор перевода на новую строку

.” A^3= “ F. CR

.” A^5= “ F. CR

.” A^10= “ F. CR

.” A^15= “ F. CR

;

Окончательно вызов слова B28 будет выглядеть, с учетом упрощения, так:

2E B28.

Так мы разделяем алгоритм работы слова с его примитивным интерфейсом вывода результатов. В таком случае при необходимости что-то доработать, одно не помешает другому и, разумеется, код становится более лаконичным и понятным.


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 )

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

: 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

Пример 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 град Фаренгейта

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

: 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

Ноль градусов по Цельсию по-прежнему 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

Проверили на тех же данных. И снова не забываем об обратном порядке при печати со стека, не важно с какого (целочисленного или вещественного). Чтобы в начале вывести цену за 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

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

Пример 35. Детская задачка на движение лодки в стоячей и движущейся воде.

VARIABLE T2

: B35 ( V U T1 T2 -> S )      \ S=S1+S2, S1=V*T1, S2=(V-U)*T2

T2 !                  \ V U T1 T2 -> V U T1

ROT DUP ROT *            \ V U T1 -> U V V*T1=S1

SWAP ROT –            \ U V S1 -> S1 V-U

T2 @ *                  \ S1 V-U -> S1 [V-U]*T2=S2

+                  \ S=S1+S1

;

Манипуляции на стеке неоправданно усложняются с четырьмя и более элементами, поэтому мы сохраним значение T2 в одноименной переменной. Сперва мы вычисляем путь S1 в стоячей воде, затем считывая время T2 из переменной – путь S2 и соответственно ему скорость. Ответ есть сумма двух путей. Проверим написанное слово.

10 5 1 1 B35

Ok ( 15 )

1 час в стоячей воде со скоростью 10 – это путь равный 10*1=10 и такое же время со скоростью 10-5=5. В итоге общий путь 10+5=15.

С вещественными данными слово будет иметь вид:

FVARIABLE FT2

: B35 ( V U T1 T2 -> S )      \ S=S1+S2, S1=V*T1, S2=(V-U)*T2

FT2 F!                  \ V U T1 T2 -> V U T1

FROT FDUP FROT F*      \ V U T1 -> U V V*T1=S1

FSWAP FROT F-            \ U V S1 -> S1 V-U

FT2 F@ F*            \ S1 V-U -> S1 [V-U]*T2=S2

F+                  \ S=S1+S1

;

10E 5E 1E 1E B35 F.

15.000000 Ok

На предыдущих данных, как и положено, дает тот же результат, но с типом float.

Пример 36. Без комментариев, сразу приведем решение.

: B36 ( V1 V2 S0 T -> S )            \ S=S0+(V1+V2)*T

2SWAP + * +            \ V1 V2 S0 T -> S0+T*(V1+V2)

;

3 5 100 2 B36

Ok ( 116 )

\ 3+5=8, 8*2=16, 16+100=116.

FVARIABLE FS0

: B36 ( V1 V2 S0 T -> S )            \ S=S0+(V1+V2)*T

FSWAP FS0 F!            \ V1 V2 S0 T -> V1 V2 T

FROT FROT F+ F*      \ V1 V2 T -> T*(V1+V2)

FS0 F@ F+            \ T*(V1+V2)+S0

;

3E 5E 100E 2E B36 F.

116.00000 Ok

По предыдущему опыту мы вводим новую переменную, чтобы уменьшить количество элементов на вещественном стеке. Ответ совпадает с первым вариантом, только вещественного формата, что подтверждает корректность теста.

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

: B37 ( V1 V2 S0 T -> S )            \ S=|S0-T*(V1+V2)|

2SWAP + * – ABS      \ V1 V2 S0 T -> |S0-T*(V1+V2)|

;

3 5 100 2 B37

Ok ( 84 )

\ 3+5=8, 8*2=16, |100-16|=84. Проверим как работает модуль, для этого положим S0=10.

3 5 10 2 B37

Ok ( 6 )

\ 3+5=8, 8*2=16, |10-16|=6. Все верно, код работает корректно.

FVARIABLE FS0

: B37 ( V1 V2 S0 T -> S )            \ S=|T*(V1+V2)-S0|

FSWAP FS0 F!            \ V1 V2 S0 T -> V1 V2 T

FROT FROT F+ F*      \ V1 V2 T -> T*(V1+V2)

FS0 F@ F- FABS            \ T*(V1+V2) –> |T*(V1+V2)-S0|

;

3E 5E 100E 2E B37 F.

84.000000 Ok

3E 5E 10E 2E B37 F.

6.0000000 Ok

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

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

: B38 ( A B -> X )                  \ X=-B/A

–1E F* FSWAP F/            \ A B -> -B/A

;

10E 3E B38 F.

–0.3000000 Ok

Код «-1E F*» можно заменить на «FNEGATE», который лучше, но для начала может быть менее наглядным.

Пример 39. Решение квадратного уравнения. Обратите внимание, что в названии вещественных переменных опущены префиксы «F», так как в этих словах используются переменные только одного типа. Если вас это пугает, то вы легко можете добавить их. Если все слова вы добавляете в один файл, то эта проблема будет актуальной, так же вы можете в названиях слов добавлять префикс I (Integer), для функций с целочисленными аргументами и F, с вещественными, иначе SP-Forth, будет выводить сообщения «B39 isn't unique ()», что не является ошибкой, но предупреждением, о том, что при вызове слова будет вызвано определенное последней слово. Могут возникнуть скрытые ошибки логики работы. Так если вы определили целочисленное слово, затем вещественное и после выполняете попеременно слова для разных аргументов, то как было сказано будет вызвана исключительно последняя реализация, что неизбежно приведет к ошибке, связанное с тем что слова будут работать с аргументами в разных стеках, в итоге, будет либо нехватка аргументов, либо порча других данных не предназначенных для этого. Изменив названия при помощи префиксов, вы избавитесь от этих проблем.

FVARIABLE A

: B39 ( A B C -> X1 X2)      \ X1,X2=(-B+-SQRT(D))/2*A

FROT FDUP A F!       F*            \ A B C -> B C*A

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

FSWAP 4E F* F- FSQRT            \ B C*A B^2 -> B SQRT{B^2-4*C*A=D}

FSWAP -1E F* FSWAP            \ B D^0.5 -> -B D^0.5

FOVER FOVER F+ A F@            \ -B D^0.5 -> -B D^0.5 –B+D^0.5 A

2E F* F/                  \ -B D^0.5 –B+D^0.5 A -> -B D^0.5 [–B+D^0.5]/[A*2]=X1

FROT FROT F- A F@            \ -B D^0.5 X1 -> X1 –B-D^0.5 A

2E F* F/                  \ X1 –B-D^0.5 A -> X1 [–B-D^0.5]/[A*2]=X2

FOVER FOVER F<            \ X1 X2 –> X1 X2 X1

IF FSWAP THEN

;

1E 4E 1E B39 F. F.

–3.7320508 -0.2679491 Ok

X^2+4*X+1=0, D=4^2-4*1*1=16-4=12. X1,X2=(-4+-12^0.5)/(2*1)=-2+-SQRT(3)

X1=-2- 1,732= -3,732, X2=-2+1,732=-0,268.

А вот случай, когда D=0

1E 2E 1E B39 F. F.

–1.0000000 -1.0000000 Ok

Если манипуляции со стеком вам не понятны, то мы можем переписать последнее слово с использованием 3-переменных A, B, C, по классической схеме.

FVARIABLE A

FVARIABLE B

FVARIABLE C

: B39 ( A B C -> X1 X2)      \ X1,X2=(-B+-SQRT(D))/2*A, X1,X2

C F! B F! A F!      \ A B C ->

B F@ FDUP -1E F* FSWAP FDUP F*      \ -> -B B^2

A F@ C F@ F* -4E F* F+ FSQRT            \ -B B^2 -> -B {B^2+A*C*(-4)}^0.5=D^0.5

FOVER FOVER F+                  \ -B D^0.5 -> -B D^0.5 -B+D^0.5

A F@ 2E F* F/                        \ -B D^0.5 -B+D^0.5-> -B D^0.5 [-B+D^0.5]/[A*2]=X1

FROT FROT F-                        \ -B D^0.5 X1 -> X1 -B-D^0.5

A F@ 2E F* F/                        \ X1 [-B-D^0.5]/[A*2]=X2

FOVER FOVER F<                  \ X1 X2 X1

IF FSWAP THEN

;

1E 4E 1E B39 F. F.

–3.7320508 -0.2679491 Ok

Ответ как в первом случае. Какой проще и понятнее решайте сами.

Пример 40. Задача решения системы из двух линейных уравнений с двумя неизвестными. Пропустим вариант с целочисленными аргументами и перейдем к общему случаю.

FVARIABLE A1 FVARIABLE B1 FVARIABLE C1

FVARIABLE A2 FVARIABLE B2 FVARIABLE C2

: B40 ( A1 B1 C1 A2 B2 C2 -> X Y ) \ X=(C1*B2-C2*B1)/D, Y=(A1*C2-A2*C1)/D, D=A1*B2-A2*B1

C2 F! B2 F! A2 F! C1 F! B1 F! A1 F!             \ A1 B1 C1 A2 B2 C2 ->

A1 F@ B2 F@ F* A2 F@ B1 F@ F* F-             \ -> A1*B2-A2*B1=D

FDUP .” D=“ FDUP F. CR                         \ D -> D D

C1 F@ B2 F@ F* C2 F@ B1 F@ F* F- FSWAP F/       \ D D -> D (C1*B2-C2*B1)/D=X

A1 F@ C2 F@ F* A2 F@ C1 F@ F* F- FROT F/       \ D X -> X (A1*C2-A2*C1)/D=Y

;

Здесь мы создали 6 новых вещественных переменных, чтобы не путаться в коэффициентах.

Первая строка – стандартное описание логики работы слова.

Вторая – сохранение значений на стеке в соответствующие переменные. На вершине находится значение последней введённой, а значит его первым и сохраняем.

Вычисление D.

Дублируем D, так как он нам понадобится два раза, также мы его копируем и печатаем для проверки промежуточных вычислений. После отладки код «.” D=“ FDUP F. CR» можно удалять.

Вычисление X

Вычисление Y

Проверим корректность работы слова на следующих данных

3x+5y=7      (A1=3      B1=5      C1=7)

6x+y=4            (A2=6      B2=1      C2=4)

3E 5E 7E 6E 1E 4E B40 F. F.

D= -27.000000

1.1111111 0.4814814 Ok

D=3*1-6*5=3-30=-27, совпадает с результатом выданном словом. X=(7*1-4*5)/(-27)=13/27=(0,481). Y=(3*4-6*7)/(-27)=(12-42)/(-27)=30/27=1,(1). Видим, что слово работает корректно.


Integer 1-30

Теперь мы решаем новую группу заданий с исключительно целочисленными параметрами. Все задания мы будем нумеровать с префиксом I, сокращение от Integer, означающее целое число.

Пример 1. Перевести см в м без округления. Здесь вы увидите всю красоту Форта.

Rm=Rcm/100 – целочисленно

: I1 ( Rcm -> Rm )

100 /

;

503 I1

Ok ( 5 )

Что означает в 503 см содержится 5 полных метров.

Пример 2. Отличается от предыдущего заменой 100 на 1000.

Mt= Mkg/1000

: I2 ( Mkg -> Mt )

1000 /

;

12683 I2

Ok ( 12 )

В 12683 кг 12 полных тонн.

Пример 3. Так же отличается от предыдущего константой. Теперь 1000 меняем на 1024.

DkB= DB/1024

: I3 ( DB -> DkB )

1024 /

;

2050 I3

Ok ( 2 )

2050 B – это 2 полных kB.

Пример 4. Так же простейшая задачка на целочисленное деление.

Для определенности A>B, результат равен A/B.

: I4 ( A B -> A/B )

/

;

15 4 I4

Ok ( 3 )

В отрезке длиной 15 размещается 3 целых отрезка длиной 4.

Пример 5. Отличается от предыдущего примера заменой целочисленного деления на взятие остатка от деления.

: I5 ( A B -> остаток{A/B} )

MOD

;

15 4 I5

Ok ( 3 )

15/4 – остаток равен 3 – все верно, результат теста корректный.

Примеры 1-5 настолько просты, что даже нет необходимости создавать соответствующие слова. Можно просто ввести число-операнд затем тело слова. Результат получите в скобках на стеке. Чтобы распечатать его и не засорять стек нажмите «.» и «Enter». Перепишем эти примеры для наглядности.

«503 100 / .»

«12683 1000 / .»

«2050 1024 / .»

«15 4 / .»

«15 4 MOD .»

Но если вы будете часто пользоваться написанным кодом, крайне желательно создавать отдельные слова-функции, также дайте им легко запоминающиеся осмысленные названия.

Пример 6. Вывести число десятков и единиц двузначного числа. Для этого используем операцию /MOD, которая одновременно вычисляет и целую часть, и остаток от деления.

: I6 ( AB -> A B )

10 /MOD SWAP

;

45 I6

Ok ( 4 5 )

Чтобы вывести в таком же порядке как на стеке слегка изменим код (помним, что сначала напечатается вершина стека, поэтому перед выводом используем команду SWAP)

45 I6 SWAP . .

4 5 Ok

Теоретически, последним штрихом, будет оформление вывода в отдельное слово, как говорилось ранее в предыдущей группе задач, по схеме:

На страницу:
3 из 4