Arsen Gonian – Язык программирования Форт (Forth). Решение задач по программированию. Версия 2. (страница 17)
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
Небольшая оптимизация кода (на две строчки короче предыдущего слова):
FVARIABLE A
: B39 ( A B C -> X1 X2) \ X1,X2=(-B+-SQRT(D))/2*A
FROT FDUP 2E F* A F! \ A B C -> B C A
F* 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 FNEGATE FSWAP \ B D^0.5 -> -B D^0.5
FOVER FOVER F+ A F@ F/ \ -B D^0.5 -> -B D^0.5 [–B+D^0.5]/(2*A)=X1
FROT FROT F- A F@ F/ \ -B D^0.5 X1 -> X1 [–B-D^0.5]/(2*A)=X2
FOVER FOVER F< \ X1 X2 –> X1 X2 X1<X2?
IF FSWAP THEN \ X2 X1 || X1 X2
;
Результат такой же, но «2*A» два раза не вычисляется, а сразу сохраняется в переменной «A», «-1E F*» заменен на «FNEGATE» – изменение знака «B» на противоположенный.
Если манипуляции со стеком вам не понятны, то мы можем переписать последнее слово с использованием трех переменных 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<X2?
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