Решение упражнения 2.86 из SICP
Сказать, какой смысл определять комплексные числа с действительными и мнимыми частями, не являющимися действительными числами, мне трудно. Тем не менее, легко представить, что в системе существует несколько различных представлений действительных чисел (например, различающихся точностью и объемом требуемой памяти). В таком случае задача имеет смысл.
Я не буду приводить весь код модифицированной системы, а просто укажу какие изменения и где потребуется внести.
Во-первых, нам понадобится заменить во внутренних операциях пакета комплексных, а также пакетов декартового и полярного представлений чисел использование стандартных операторов сложения, вычитания, умножения и деления на соответствующие обобщенные процедуры. Соответствующие изменения будут выглядеть так:
;install-complex-package (define (add-complex z1 z2) (make-from-real-imag (add (real-part z1) (real-part z2)) (add (imag-part z1) (imag-part z2)))) (define (sub-complex z1 z2) (make-from-real-imag (sub (real-part z1) (real-part z2)) (sub (imag-part z1) (imag-part z2)))) (define (mul-complex z1 z2) (make-from-mag-ang (mul (magnitude z1) (magnitude z2)) (add (angle z1) (angle z2)))) (define (div-complex z1 z2) (make-from-mag-ang (div (magnitude z1) (magnitude z2)) (sub (angle z1) (angle z2))))
;install-rectangular-package (define (magnitude z) (sqrt (add (square (real-part z)) (square (imag-part z))))) (define (make-from-mag-ang r a) (cons (mul r (cosine a)) (mul r (sine a))))
;install-polar-package (define (real-part z) (mul (magnitude z) (cosine (angle z)))) (define (imag-part z) (mul (magnitude z) (sine (angle z)))) (define (make-from-real-imag x y) (cons (sqrt (add (square x) (square y))) (arctan y x)))
Обратите внимание, на то, что имена тригонометрических процедур изменились. Это неспроста!
Во-вторых, нам потребуется реализовать процедуры, использующиеся при переводе из полярного в декартовое представления и обратно, как обобщенные операции для всех типов чисел, которые мы хотим разрешить для использования в компонентах комплексного числа, и добавить эти обобщенные операции в систему (обобщенная процедура плюс набор реализаций для каждого типа).
Операции, которые требуется сделать обобщенными:
- square
- sqrt
- sin
- cos
- atan
На самом деле square и sqrt можно и не делать обобщенными операциями, а просто заменить в их определениях арифметические операции на обобщенные. Например, так:
(define (square x) (mul x x)) (define (average x y) (div (add x y) 2.0)) (define (sqrt x) (fixed-point (average-damp (lambda (y) (div x y))) 1.0))
Однако при этом константы 1.0 и 2.0 (или любые другие типизированные константы) вынудят систему приводить типы.
Описывать реализацию sin, cos и atan как обобщенных операций полностью я не буду. Она абсолютно аналогична ранее введенным обобщенным операциям. Так же добавляются определения обобщенных процедур (они будут называться несколько иначе: sine, cosine и arctan) через apply-generic и конкретные процедуры для каждого типа добавляются с помощью put в таблицу типов в каждом пакете. Для обычных чисел это будет выглядеть так:
;generic functions (define (sine x) (apply-generic 'sine x)) (define (cosine x) (apply-generic 'cosine x)) (define (arctan x) (apply-generic 'arctan x))
;install-scheme-number-package (put 'sine '(scheme-number) (lambda (x) (tag (sin x)))) (put 'cosine '(scheme-number) (lambda (x) (tag (cos x)))) (put 'arctan '(scheme-number scheme-number) (lambda (x y) (tag (atan x y))))
Для других типов все аналогично и выписать реализацию несложно.
Comments
Comment from Sergk
Date: April 14, 2015, 5:16 pm
Дальше, как я понимаю, у Вас нет решённых упражнений? Спасибо за проделанную работу было очень приятно сверяться с Вашими решениями!
Comment from Abra-kadabr
Date: January 4, 2016, 8:51 am
Write a comment