Arsen Gonian – Язык программирования Форт (Forth). Решение задач по программированию. Версия 2. (страница 6)
Протестируем на числах 4 и 2.
4 2 B10
Ok ( 20 12 64 4 )
Всё корректно, проверяйте самостоятельно. В комментариях я сократил сумму, разность и произведение квадратов до соответствующих операций в скобках. Специально подобраны такие числа, чтобы результат деления был целочисленным, но это не обязательно – код для вещественных аргументов избавит нас от таких неудобств:
: B10 ( A B -> A^2+B^2 A^2-B^2 A^2*B^2 A^2/B^2 )
FSWAP FDUP F* \ A B -> B A^2
FSWAP FDUP F* \ B A^2 -> A^2 B^2
FOVER FOVER F+ \ A^2 B^2 -> A^2 B^2 (A^2+B^2)=(+)
FROT FROT FOVER FOVER F- \ A^2 B^2 (+) -> (+) A^2 B^2 (A^2-B^2)=(-)
FROT FROT FOVER FOVER F* \ (+) A^2 B^2 (-) -> (+) (-) A^2 B^2 (A^2*B^2)=(*)
FROT FROT F/ \ (+) (-) A^2 B^2 (*) -> (+) (-) (*) (A^2/B^2)=(/)
;
Тест примера 10:
1E-1 2E-1 B10 F. F. F. F.
0.2500000 0.0004000 -0.0300000 0.0500000 Ok
Не забываем, что оператор F. Печатает число с вершины стека, поэтому сначала печатается частное, затем произведение, после чего разность и в конце сумма.
0,25 = 0,01/0,04; 0,0004 = 0,01*0,04; -0,03 = 0,01-0,04; 0,05 = 0,01+0,04.
Если вам нужен другой порядок вывода результатов, то самостоятельно решите эту задачу для обоих вариантов, слова ниписаны в соответствии со стековой нотацией.
Полезные слова (если переименовать и разбить некоторые из приведенных выше, то получим список, который можете использовать как свою маленькую математическую библиотеку):
: SquarePerimeter ( a -> P=4*a ) 4E F* ;
: SquareArea ( a -> S=a*a ) FDUP F* ;
: RectanglePerimeter ( a b -> P=2*[a+b] ) F+ 2E F* ;
: RectangleArea ( a b -> S=a*b ) F* ;
: CircleLength ( r -> l=2*Pi*r ) 2E FPI F* F* ;
: CircleArea ( r -> S=Pi*r*r ) FDUP F* FPI F* ;
: CubeVolume ( a -> V=a*a*a ) FDUP FDUP F* F* ;
: CubeLateralSurfaceArea ( a -> S=6*a*a ) FDUP F* 6E F* ;
: RectangularPrismVolume ( a b c -> V=a*b*c ) F* F* ;
: RectangularPrismLateralSurfaceArea ( a b c -> S=2*[a*b+b*c+a*c] ) FOVER FOVER F+ FROT FROT F* FSWAP FROT F* F+ 2E F* ;
: ArithmeticMean ( a b -> [A+B]/2 ) F+ 2E F/ ;
: GeometricMean ( a b -> SQRT[A*B] ) F* FSQRT ;
Тесты проведите самостоятельно.
BEGIN 11-20
Пример 11. Отличается от 10-ого примера незначительными поправками. Просто заменяем квадрат на модуль: код «DUP *» на «ABS» (и «FDUP F*» на «FABS» для вещественных аргументов).
: B11 ( A B -> {|A|+|B|} {|A|-|B|} {|A|*|B|} {|A|/|B|} )
SWAP ABS SWAP ABS \ A B ->|A| |B|
2DUP + \ |A| |B|-> |A| |B| (|A|+|B|)
ROT ROT 2DUP – \ |A| |B| (|A|+|B|) -> (|A|+|B|) |A| |B| (|A|-|B|)
ROT ROT 2DUP * \ (+) |A| |B| (-) -> (+) (-) |A| |B| (|A|*|B|)
ROT ROT / \ (+) (-) |A| |B| (*)-> (+) (-) (*) (|A|/|B|)
;
В случае для вещественных аргументов:
: B11 ( A B -> {|A|+|B|} {|A|-|B|} {|A|*|B|} {|A|/|B|} )
FSWAP FABS \ A B -> B |A|
FSWAP FABS \ B |A| -> |A| |B|
FOVER FOVER F+ \ |A| |B|-> |A| |B| (|A|+|B|)=(+)
FROT FROT FOVER FOVER F- \ |A| |B| (+) -> (+) |A| |B| (|A|-|B|)=(-)
FROT FROT FOVER FOVER F* \ (+) |A| |B| (-) -> (+) (-) |A| |B| (|A|*|B|)=(*)
FROT FROT F/ \ (+) (-) |A| |B| (*)-> (+) (-) (*) (|A|/|B|)=(*)
;
В комментариях (скобках) соответствующие сумма, разность, произведение и частное взяты в фигурные скобки для визуального выделения элементов на стеке. Обычные скобки в данном случае применять нельзя, так как они обозначают комментарий и являются зарезервированными словами Форта и системы программирования SP-Forth в частности.
Тесты на корректность работы написанных слов произведите самостоятельно.
Пример 12. Вычислить гипотенузу и периметр прямоугольного треугольника по его катетам. Так как мы имеем дело с квадратным корнем, сразу приведем код для случая с вещественным аргументом.
: B12 ( A B -> C P ) \ C=Квадратный_Корень(A^2+B^2) P=A+B+C
FOVER FDUP F* \ A B -> A B A^2
FOVER FDUP F* \ A B A^2 -> A B A^2 B^2
F+ FSQRT \ A B A^2 B^2 -> A B Квадратный_Корень(A^2+B^2)=C
FROT FROT F+ \ A B C -> C A+B
FOVER F+ \ C A+B -> C A+B+C=P
;
Проверим на прямоугольном треугольнике с катетами 3 и 5:
3E 4E B12 F. F. \ вызываем нашу подпрограмму и печатаем результат
12.000000 5.0000000 Ok