Пример одиннадцать. Найти сумму квадратов от N до 2* N. Схема работы аналогична предыдущим примерам, так же заводим счетчик на стеке, пределы параметра цикла абсолютно такие же, перед суммированием возводим каждый элемент в квадрат.
: FOR11 ( N>0 -> ) \ N^2+[N+1]^2+[N+2]^2+…+[2*N]^2
0 \ N -> N 0 = Sum – итоговая сумма
OVER 1+ 0 \ N>0 Sum -> N Sum N+1 0 – последние 2 числа пределы цикла
DO \ N Sum N+1 0 -> N Sum
OVER I + DUP * + \ N Sum -> N Sum+(N+I)^2
LOOP . DROP ; \ Sum – результат печатаем, N – лишнее удаляем
\ Тест примера одиннадцать:
3 FOR11
86 Ok
4 FOR11
190 Ok
5 FOR11
355 Ok
Проверим для тройки: (3+0)^2+(3+1)^2+(3+2)^2+(3+3)^2= 9+16+25+36=86 – все верно.
Пример двенадцать. Найти произведение N сомножителей 1,1*1,2*… . Здесь в цикле для N элементов нужно вычислить каждый по формуле (1+0,1*N) и умножить ее с общим значением произведения, начальное значение которой будет единицей.
: FOR12 ( N>0 -> ) \ 1.1*1.2*1.3*...
1+ 1 \ I: N -> N+1 1
1E \ F: 1 = P
DO \ I: N+1 1 ->
I 0 D>F 10E F/ 1E F+ \ F: P -> P 1+0.1*I
F* \ P 1+0.1*I -> P*(1+0.1*I)
LOOP F. ; \ P*(1+0.1*I) – печатаем итоговое произведение
\ Тесты для двенадцатого примера:
1 FOR12
1.1000000 Ok
2 FOR12
1.3200000 Ok
3 FOR12
1.7160000 Ok
4 FOR12
2.4024000 Ok
5 FOR12
3.6036000 Ok
1,1 – первый элемент (1 FOR12), для двух элементов получаем (1,1*1,2)=1,32 (2 FOR12), для трех - предыдущий умножаем на 1,3 получаем (1,1*1,2*1,3)=1,716 (3 FOR12), далее проверяйте самостоятельно.
Пример тринадцать. Схож с предыдущим, произведение заменяем на сумму и для каждого элемента меняем знак на противоположенный, умножением на минус один. Для этого заводим переменную, которую инициализируем единицей, далее после расчета очередного члена ряда меняем его знак.
FVARIABLE S \ S – SIGN переменная знак
: FOR13 ( N>0 -> ) \ 1.1-1.2+1.3-...
1E S F! \ первоначально присвоим единицу, каждый раз при вызове слова снова
1+ 1 \ I: N -> N+1 1 – пределы параметра цикла
0E \ F: 0 = Sum
DO \ I: N+1 1 ->
I 0 D>F 10E F/ 1E F+ \ F: Sum -> Sum 1+0.1*I
S F@ FDUP FNEGATE S F! F* \ F: Sum 1+0.1*I -> Sum (1+0.1*I)*S , S = - S
F+ \ Sum (1+0.1*I)*S -> Sum+(1+0.1*I)*S
LOOP F. ;
\ Традиционно тест-слово, которое поможет не вводить по многу раз однотипные данные:
: TEST-FOR13 10 1 DO I DUP . FOR13 CR LOOP ;
TEST-FOR13
1 1.1000000
2 -0.1000000
3 1.2000000
4 -0.2000000
5 1.3000000
6 -0.3000000
7 1.4000000
8 -0.4000000
9 1.5000000
Ok
Пример четырнадцать. Вычисляем квадрат числа по формуле (сумма ряда), не используя умножение. Слово должно вывести квадраты всех целых чисел от 1 до N включительно.
: FOR14 ( N>0 -> ) \ N^2=1+3+5+...+{2*N-1}
1+ 1 0 ROT ROT \ N -> 0 N+1 1 - стандартные пределы параметра цикла
DO \ 0 N+1 1 -> 0=Sum – сумма ряда
I 2* 1- + DUP . \ Sum -> Sum+(2*I-1) – текущая сумма ряда, дублируем и печатаем
LOOP DROP ; \ перед выходом оставляем стек как было, сняв исходный параметр
\ Тест слово для автоматического тестирования, выводит следующие красивые данные:
: TEST-FOR14 11 1 DO I FOR14 CR LOOP ;
TEST-FOR14
1
1 4
1 4 9
1 4 9 16
1 4 9 16 25
1 4 9 16 25 36
1 4 9 16 25 36 49
1 4 9 16 25 36 49 64
1 4 9 16 25 36 49 64 81
1 4 9 16 25 36 49 64 81 100
Ok
Пример пятнадцать. Данное вещественное число возвести в целую степень умножением на само себя, соответственное количество раз.
: FOR15 ( F: A I: N>0 -> ) \ 1.5E 5 FOR15 – формат использования слова, выводит A^N
1E \ F: A –> A 1=P – степень исходного числа, первоначально равно единице
0 \ I: N>0 -> I: N>0 0 - нижняя граница параметра цикла
DO
FOVER F* \ A P -> A P*A – просто P равное единице N раз умножаем на A
LOOP F. FDROP ; \ Печатаем степень и удаляем исходное число A
\ Протестируем, возведя два в степени от 1 до 10, тест-словом:
: TEST-FOR15 11 1 DO 2E I FOR15 LOOP ;
TEST-FOR15
2.0000000 4.0000000 8.0000000 16.000000 32.000000 64.000000 128.00000 256.00000 512.00000 1024.0000 Ok
Небольшой прикол в работе слова FOR15, так как оба параметра слова находятся в разных стеках, то неважно в каком порядке их вводить, а это значит, что примеры
2E 1 FOR15
1 2E FOR15
дадут одинаковый и правильный результат, несмотря на неправильный синтаксис и логику.
В Форте возвести число в степень можно и более традиционным способом «в одно действие»:
: FOR15 ( F: A N -> ) \ A^N
F** F. ;
2E 10E FOR15
1024.0000 Ok
Два в десятой 1024. Здесь уже порядок важен и оба параметра вещественные, ибо для целого нужно переводить его в вещественный стек. Код стал гораздо короче, но первый вариант служит наглядным примером работы циклов, а не эффективного возведения числа в степень.
Пример шестнадцать. Получаем из предыдущего небольшими изменениями. Теперь результат печатаем не один раз (в конце после «LOOP»), а каждый раз внутри цикла, после расчета очередной степени «FOVER F*».
: FOR16 ( F: A I: N>0 -> ) \ 1.5E 5 FOR15 – формат использования слова, выводит A A^2 … A^N
1E \ F: A –> A 1=P – степень исходного числа, первоначально равно единице
0 \ I: N>0 -> I: N>0 0 - нижняя граница параметра цикла
DO
FOVER F* FDUP F. CR \ A P -> A P*A – дублируем P*A и выводим на экран
LOOP FDROP ; \ удаляем исходное число A
\ Пример работы слова:
2E 10 FOR16
2.0000000
4.0000000
8.0000000
16.000000
32.000000
64.000000
128.00000
256.00000
512.00000
1024.0000
Ok
\ Если убрать «CR» в цикле после вывода очередной степени, то получим:
2E 10 FOR16
2.0000000 4.0000000 8.0000000 16.000000 32.000000 64.000000 128.00000 256.00000 512.00000 1024.0000 Ok
Абсолютно идентичен работе тест слова из примера 15 (TEST-FOR15).
Пример семнадцать. Выведенные степени в предыдущем примере теперь просто суммируем и выводим один результат. Используем переменную вещественного типа, в ней будем хранить итоговую сумму.
FVARIABLE F1
: FOR17 ( F: A I: N>0 -> ) \ 1.5E 5 FOR17 – форма вызова слова, выводим 1+A+A^2+A^3+...+A^N
1E FDUP F1 F! \ 1 = P – степень A вначале присваиваем единицу, дублируем и сохраняем в F1
0 \ N -> N 0 - нижняя граница цикла
DO \ N 0 ->
FOVER F* FDUP \ F: A 1 -> A 1*A 1*A
F1 F@ F+ F1 F! \ F1=1*A+F1
LOOP
F1 F@ F. FDROP FDROP ; \ F1. – распечатка результата, у удаление ненужных данных
Протестируем для A=2 (в этом случае получим очень интересные числа), тест слово прогоним от 1 до 10, думаю этого должно быть достаточно.
: TEST-FOR17 11 1 DO 2E ." N=" I DUP . FOR17 CR LOOP ;
TEST-FOR17
N=1 3.0000000
N=2 7.0000000
N=3 15.000000
N=4 31.000000
N=5 63.000000
N=6 127.00000
N=7 255.00000
N=8 511.00000
N=9 1023.0000
N=10 2047.0000
Ok
Поэкспериментируйте с другими основаниями самостоятельно.
Пример восемнадцать. Получим из предыдущего умножением в цикле каждого члена суммы на минус единицу, таким образом поменяв ему знак мы получаем знакочередующийся ряд (как в условии).
FVARIABLE F1
: FOR18 ( F: A I: N -> ) \ 1.5E 5 FOR18 – пример вызова, результат 1-A+A^2-A^3+...+(-1) ^N*A^N
1E FDUP F1 F! \ F: A -> A 1=P – дублируем 1 и сохраняем в F1 = сумма ряда
0 \ I: N -> N 0 – границы параметра цикла
DO \ N 0 ->
FOVER F* \ A P -> A P*A
-1E F* FDUP \ A P*A -> A P*A*(-1) P*A*(-1)
F1 F@ F+ F1 F! \ F1=F1+(P*A*(-1))
LOOP
F1 F@ F. \ распечатка итоговой суммы ряда
FDROP FDROP ; \ очистка оставшихся данных
: TEST-FOR18 11 1 DO 2E I DUP . FOR18 CR LOOP ;
\ Результат работы тест слова TEST-FOR18:
TEST-FOR18
1 -1.0000000
2 3.0000000
3 -5.0000000
4 11.000000
5 -21.000000
6 43.000000
7 -85.000000
8 171.00000
9 -341.00000
10 683.00000
Ok
Квадраты двойки: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024.
Получим ряд: 1-2=-1; -1+4=3; 3-8=-5; -5+16=11; 11-32=-21; -21+64=43; 43-128=-85; -85+256=171…
Пример девятнадцать. Вычисляем факториал в вещественном формате (так сказать определяем его порядок, а не точное целочисленное значение).
: FOR19 ( N>0 -> ) \ N! – вывести факториал
1+ 1 \ N –> N+1 1 – пределы параметра цикла
1E \ F: 1E=Fact – значение факториала вначале равно единице
DO \ N+1 1 ->
I 0 D>F F*
\ F: Fact -> Fact*I – I переводим в слово двойной точности, просто добавив
\ ноль, чтобы потом перевести его на вещественный стек, и умножаем на Fact
LOOP
G. ; \ распечатка результата
Слово «F.» поменял на «G.», чтобы был показатель. Так как формат первого не показывает его. Итоговая работа тест слова:
: TEST-FOR19 20 1 DO I DUP . ." != " FOR19 CR LOOP ;
TEST-FOR19
1 != 1.0000000
2 != 2.0000000
3 != 6.0000000
4 != 24.000000
5 != 120.00000
6 != 720.00000
7 != 5040.0000
8 != 40320.000
9 != 362880.00
10 != 3628800.0
11 != 39916800.
12 != 4.7900160e08
13 != 6.2270208e09
14 != 8.7178291e10
15 != 1.3076744e12
16 != 2.0922790e13
17 != 3.5568743e14
18 != 6.4023737e15
19 != 1.2164510e17
Ok
Пример двадцать. Можем получить из предыдущего небольшой ее модификацией. Добавляем S – сумма факториалов (строка три). И прибавляем в девятой строке к этой сумме текущий факториал. Перед распечаткой ответа сбрасываем последний текущий факториал.
: FOR20 ( N>0 -> ) \ 1!+2!+…+N! – вывести сумму факториалов
1+ 1 \ I: N –> N+1 1 – пределы параметра цикла
0E \ F: 0E= S – значение суммы факториалов вначале равно нулю
1E \ F: S -> S 1=F - текущий факториал
DO \ N+1 1 ->
I 0 D>F F*
\ F: S F -> S F*I – I переводим в слово двойной точности, просто добавив
\ ноль, чтобы потом перевести его на вещественный стек, и умножаем на F
FSWAP FOVER F+ FSWAP \ S F*I -> S+F*I F*I
LOOP
FDROP G. ; \ распечатка результата
\ Тест слово для FOR20 на диапазоне данных от 1 до 10:
: TEST-FOR20 21 1 DO I FOR20 CR LOOP ;
TEST-FOR20
1.0000000
3.0000000
9.0000000
33.000000
153.00000
873.00000
5913.0000
46233.000
409113.00
4037913.0
43954713.
5.2295631e08
6.7499771e09
9.3928268e10
1.4016026e12
2.2324393e13
3.7801182e14
6.7803855e15
1.2842549e17
2.5613275e18
Ok