Пример тридцать один.
: FOR31 ( N>0 -> ) \ выводим A1 A2 ... AN
2E \ A0=2
0 \ N –> N 0 , пределы цикла
DO
1E FSWAP F/ \ A0 -> 1/A0
2E F+ \ 1/A0 -> 1/A0+2
FDUP F. \ вывод копию 2+1/A0
LOOP FDROP ; \ сбрасываем последний «2+1/A0», очищаем стек после себя
\ Результат работы программы (при N=10):
10 FOR31
2.5000000 2.4000000 2.4166667 2.4137931 2.4142857 2.4142012 2.4142157 2.4142132 2.4142136 2.4142136 Ok
Пример тридцать два.
: FOR32 ( N>0 -> ) \ выводим последовательность чисел A1 A2 ... AN
1E \ A0=1
1+ 1 \ N –> N 0 , пределы цикла
DO
1E F+ \ A[k-1]+1
I S>D D>F F/ \ (A[k-1]+1)/I , «I – это k в нашем случае»
FDUP F. \ вывод копию (A[k-1]+1)/I
LOOP FDROP ;
\ Пример работы слова (при N=10):
10 FOR32
2.0000000 1.5000000 0.8333333 0.4583333 0.2916666 0.2152777 0.1736111 0.1467013 0.1274112 0.1127411 Ok
Пример тридцать три.
: FOR33 ( N>1 -> ) \ вывести F1, F2, ... FN, если F1=1, F2=1, FK=F[K-2]+F[K-1]
DUP 3 < \ N –> N N<3
IF DROP 1 . 1 . EXIT THEN \ Если «N<3», то печатаем «1 1» и выходим
1 . 1 . \ печатаем первые два элемента «1 1»
1 1 ROT \ N -> 1 1 N , иначе считаем FN
1+ 3 \ 1 1 N -> 1 1 N+1 3 – готовим пределы цикла
DO \ 1 1 N+1 3 -> 1 1
2DUP + \ 1 1 -> 1 1 1+1 , из предыдущих двух получаем очередной элемент
ROT DROP \ F[K-2] F[K-1] F[K] -> F[K-1] F[K] , удаляем элемент F[K-2]
DUP . \ вывод копию F[K]
LOOP DROP DROP ;
Проверим для двадцати первых чисел Фибоначчи (можем увидеть, что эта функция довольно быстро растет, будьте осторожнее с переполнением при вычислении большого количества членов ряда, так 46-ой элемент равен «1836311903», а 47-ой выдаст отрицательным из-за переполнения, если операции переписать для работы с положительными числами, дальше 48-ого элемента не продвинемся, можно переписать с операциями для чисел двойной точности при необходимости, но и их можно «преодолеть» при большом желании, компьютер – это просто вычислительная машина, а не «волшебное устройство»):
20 FOR33
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 Ok
Пример тридцать четыре. Идентичен предыдущему (отличается только формулой), получаем из нее небольшими изменениями и заменой операций для целочисленных чисел на вещественные (из-за деления в формуле для AK).
: FOR34 ( N>1 -> ) \ вывести A1=1 A2=2 ... AK={A[K-2]+2*A[K-1]}/3 ... AN
DUP 3 < \ N –> N N<3
IF DROP 1 . 2 . EXIT THEN \ Если «N<3», то печатаем «1 2» и выходим
1 . 2 . \ иначе считаем FN, печатаем первые два элемента «1 2»
1E 2E \ F: -> 1 2 , первые два элемента
1+ 3 \ N -> N+1 3 – готовим пределы цикла
DO \ N+1 3 ->
FDUP 2E F* \ F: 1 2 -> A[K-2] A[K-1] A[K-1]*2
FROT F+ 3E F/ \ A[K-2] A[K-1] A[K-1]*2 -> A[K-1] (A[K-1]*2+A[K-2])/3
FDUP F. \ вывод копию (A[K-1]*2+A[K-2])/3
LOOP FDROP FDROP ;
В результате работы вышенаписанного кода получаем следующий ряд чисел:
10 FOR34
1 2 1.6666667 1.7777778 1.7407407 1.7530864 1.7489712 1.7503429 1.7498857 1.7500381 Ok
Пример тридцать пять. Здесь очередной член считается не через два, а три предыдущих. В целом мало отличается от предыдущих примеров. Во второй строке сравниваем N с четыре (вместо три), если меньше печатаем три первых элемента и выходим (решил сильно не заморачиваться). Иначе в четвертой печатаем первые три элемента и вычисляем остальные далее. В пятой заносим первые три члена для расчета очередного. В шестой готовим параметры цикла, за которым идет сам цикл. В цикле все должно быть знакомо, дублируем два верхних элемента и складываем. Так как с четырьмя элементами работать сложно (не захотелось прибегать к переменным), то мы этот промежуточный результат отправляем на стек возвратов (слово «>R»), после выносим элемент A[K-3] на вершину и умножаем его на «-2», после возвращаем со стека возвратов промежуточное значение суммы и вычисляем окончательный результат (таким образом за одно избавились от A[K-3] элемента, за не надобностью). Остальное стандартно – копируем последний, вычисленный элемент и выводим его на экран, и после цикла очищаем стек от трех элементов. Единственное нововведение – это работа со стеком возвратов. С ним нужно обращаться особенно осторожно, если занести туда что-то (или снять) и вызвать другое слово, или использовать любую конструкцию меняющую порядок исполнения программы (может зависеть от реализации работы компилятора/интерпретатора, смотря где хранятся данные цикла, условных операторов и т. д., любое изменение количества элементов на стеке возвратов или изменение их значений предсказуемо опасно «для здоровья программ», лучше не рисковать), то гарантированно программа вылетит с ошибкой. Стек возвратов служит для организации иерархии вызовов подпрограмм и переключения между программами и реализован на уровне железа (по крайней мере в архитектуре x86).
: FOR35 ( N>2 -> ) \ вывести F1, F2, ... FN, если F1=1, F2=2, F3=3, AK=A[K-1]+A[K-2]-2*A[K-3]
DUP 4 < \ N –> N N<3
IF DROP 1 . 2 . 3 . EXIT THEN \ Если «N<3», то печатаем «1 2 3» и выходим
1 . 2 . 3 . \ печатаем первые три элемента «1 2 3»
1 2 ROT 3 SWAP \ N -> 1 2 3 N , иначе считаем FN
1+ 4 \ 1 2 3 N -> 1 2 3 N+1 3 – готовим пределы цикла
DO \ 1 2 3 N+1 3 -> 1 2 3
2DUP + \ 1 2 3 -> 1 2 3 2+3
>R \ 1 2 3 2+3 -> 1 2 3
ROT -2 * \ 1 2 3 -> 2 3 1*(-2)
R> \ 2 3 1 -> 2 3 1*(-2) 2+3
+ \ 2 3 1*(-2) 2+3 -> 2 3 1*(-2)+2+3
DUP . \ вывод копию (A[K-1]+A[K-2]-2*A[K-3])/3
LOOP DROP DROP DROP ;
\ Проверим при N=20:
20 FOR35
1 2 3 3 2 -1 -5 -10 -13 -13 -6 7 27 46 59 51 18 -49 -133 -218 Ok
Пример тридцать шесть. Не особо сложная задача со вложенными циклами, требующая чуть большей внимательности, и главное не забывать о необходимости каждый раз оставлять данные для пределов параметра вложенного цикла. Строки два, три и четыре готовят пределы внешнего цикла и отправляют на вещественный стек ноль (начальное значение итоговой суммы ряда). Далее идет подготовка к вложенному циклу седьмая строка, а в шестой в вещественный стек отправляем N, равный текущему значению итерации (член ряда, который необходимо возвести в степень) и единицу как начальное значение степени N, а после непосредственно сам цикл, который возводит в степень многократным умножением. Затем сбрасываем N и суммируем два оставшихся на вершине стеке числа, получив текущую сумму ряда. После внешнего цикла печатаем итоговый результат словом «G.» (для корректного отображения экспоненты) и удаляем оставшийся на целочисленном стеке входной параметр «K».
: FOR36 ( N>0 K>0 -> ) \ вычислить 1^K+2^K+...+N^K
SWAP \ N K -> K N
1+ 1 \ K N -> K N+1 1, прогоняю сперва все N
0E \ F: -> 0, заносим в вещественный стек ноль – начальное значение суммы ряда
DO \ K N+1 1-> K
I S>D D>F 1E \ F: 0 -> 0 N 1, добавили «1» –начальное значение произведения «N^K»
DUP 1+ 1 \ K -> K K+1 1
DO \ K K 1 -> K
FOVER F* \ F: 0 N 1 -> 0 N 1*N
LOOP
FSWAP FDROP F+ \ F: 0 N 1*N -> 0+N^K
LOOP G. DROP ;
\ Примеры вычисления суммы квадратов от 1 до 5, 6, 7 и до 10 в 10-ой степени (для проверки правильности вывода экспоненты):
5 2 FOR36
55.000000 Ok
6 2 FOR36
91.000000 Ok
7 2 FOR36
140.00000 Ok
10 10 FOR36
1.4914342e10 Ok
Данный пример можно переписать без вложенного цикла. Форт имеет встроенное средство для возведения в степень одной операцией. Просто приведу пример возведения в степень, при желании сами модифицируйте вышеописанный код, ибо пример должен показывать использование цикла в цикле, а не мастерство и знания. Пример 5 в степени 5:
5E 5E F** F.
3125.0000 Ok
Пример тридцать семь. Модификация предыдущего, в котором предел параметра внутреннего цикла «K» заменен текущем значением параметра внешнего цикла. В общем, минимум правок и задача решена.
: FOR37 ( N>0 -> ) \ вычислить 1^1+2^2+...+N^N
1+ 1 \ I: N -> N+1 1, прогоняю все N
0E \ F: -> 0, заносим в вещественный стек ноль – начальное значение суммы ряда
DO \ I: N+1 1->
I DUP \ I: I I, (I=N)
S>D D>F 1E \ F: 0 -> 0 N 1, «1» – это начальное значение произведения «N^N»
1+ 1 \ I: I -> I+1 1
DO \ I: I+1 1 ->
FOVER F* \ F: 0 N 1 -> 0 N 1*N
LOOP
FSWAP FDROP F+ \ F: 0 N 1*N -> 0+N^N
LOOP G. ;
\ Тесты:
1 FOR37
1.0000000 Ok
2 FOR37
5.0000000 Ok
3 FOR37
32.000000 Ok
4 FOR37
288.00000 Ok
5 FOR37
3413.0000 Ok
Пример тридцать восемь. Чтобы прогнать степени в обратном порядке, мы дополнительно копируем входной параметр «N», а из него вычисляем «N-I+1» (к примеру, для «N=5», «I=1» – «N-I+1=5-1+1=5», «I=2» - «N-I+1=5-2+1=4 … и «I=5» - «N-I+1=5-5+1=1, получив таким образом обратный отсчет для параметра вложенного цикла). В остальном все как в предыдущих примерах.
: FOR38 ( N>0 -> ) \ вычислить 1^N+2^(N-1)+...+N^1
DUP 1+ 1 \ I: N -> N N+1 1, прогоняю все N
0E \ F: -> 0, заносим в вещественный стек ноль – начальное значение суммы ряда
DO \ I: N N+1 1-> N
I DUP \ I: N -> N I I, (I=N)
S>D D>F 1E \ F: 0 -> 0 N 1, «1» – это начальное значение произведения «N^N»
OVER SWAP – \ I: N I -> N N-I
1+ 1 SWAP \ I: N N-I -> N 1 N-I+1
DO \ I: N 1 N-I+1 -> N
FOVER F* \ F: 0 N 1 -> 0 N 1*N
-1
+LOOP
FSWAP FDROP F+ \ F: 0 N 1*N -> 0+N^N
LOOP G. DROP ;
\ Тесты дают следующие результаты:
1 FOR38
1.0000000 Ok
2 FOR38
3.0000000 Ok
3 FOR38
8.0000000 Ok
4 FOR38
22.000000 Ok
5 FOR38
65.000000 Ok
Пример тридцать девять. Простейший пример после предыдущих. Во внешнем цикле, прогоняем I от A до B, а во внутреннем - текущее значение параметра печатаем количество раз равное его значению.
: FOR39 ( A>0 B>0 -> ) \ A (A раз) A+1 (A+1 раз)… A+N (A+N раз) {A<B}
1+ SWAP ( B+1 A ) \ A B -> B+1 A
DO \ B+1 A ->
I DUP 0 \ -> I I 0, от нуля до (I-1), то есть «I» раз повторяем вложенный цикл
DO \ I I 0 -> I
DUP . \ печатаем I (I= от A до B) I раз
LOOP
DROP \ удаляем I за ненадобностью, оставляем стек чистым после себя
LOOP ;
\ Тест:
2 7 FOR39
2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 7 7 7 Ok
Пример сорок. В строке два отправляю на стек единицу – начальное значение числа повторений и пределы параметра цикла. С третьей по девятую внешний цикл. Четвертая – пределы параметра внутреннего цикла, и с пятой по седьмую строки вложенного цикла, внутри которой дублируем «I» и печатаем ее (текущее значение параметра внешнего цикла), после которого сбрасывается «I» и увеличивается число повторений вывода текущего числа на единицу за которым идет «CR» - просто для красоты вывода и удобства подсчета количества повторений во время проверки результатов.
: FOR40 ( A>0 B>0 -> ) \ A (1 раз) A+1 (2 раз)… A+N (N раз) {A<B}
1+ SWAP 1 ROT ROT \ A B -> 1 B+1 A, пределы цикла, а один - начало числа повторений
DO \ 1 B+1 A ->1
I OVER 0 \ 1 -> 1 I 1 0
DO \ 1 I 1 0 -> 1 I
DUP . \ печатаю «I» … раз
LOOP
DROP 1+ CR \ 1 I -> 1+1, сбрасываю «I» и увеличиваю число повторений
LOOP DROP ; \ сбрасываю число повторений
\ По традиции тест:
1 10 FOR40
1
2 2
3 3 3
4 4 4 4
5 5 5 5 5
6 6 6 6 6 6
7 7 7 7 7 7 7
8 8 8 8 8 8 8 8
9 9 9 9 9 9 9 9 9
10 10 10 10 10 10 10 10 10 10
Ok