(a)添加gcd-factor获得系数的方法,然后将系数乘到第一个多项式上,再进行运算
(define (remainder-terms a b)
(cadr (div-terms a b)))
(define (gcd-factor L1 L2)
(let ((t1 (first-term L1))
(t2 (first-term L2)))
(let ((o1 (order t1))
(o2 (order t2))
(c (coeff t2)))
(expt c (- (+ 1 o1) o2)))))
(define (pseudoremainder-terms a b)
(remainder-terms (mul-term-by-all-terms (make-term 0 (gcd-factor a b)) a) b))
(define (gcd-terms a b)
(if (empty-termlist? b)
a
(gcd-terms b (pseudoremainder-terms a b))))
文章最后会列出完整程序,运行结果
'(polynomial x sparse (4 11) (3 -22) (2 18) (1 -14) (0 7))
'(polynomial x sparse (3 13) (2 -21) (1 3) (0 5))
'(polynomial x sparse (2 1458) (1 -2916) (0 1458))
(b)求出个系数的最大公约数,然后每个系数除以公约数进行化简
;;gcd-terms添加每个系数除以最大公约数
(define (gcd-terms a b)
(if (empty-termlist? b)
a
(let ((reslut (gcd-terms b (pseudoremainder-terms a b))))
(mul-term-by-all-terms (make-term 0 (/ 1 (gcd-coeff-term reslut))) reslut))))
;;gcd-coeff-term获得各个系数的最大公约数
(define (gcd-coeff-term a)
(cond ((= (length a) 1) (coeff (first-term a)))
((null? a) 1)
(else (gcd (coeff (first-term a)) (gcd-coeff-term (rest-termsa))))))
运行结果等于p1多项式,证明没问题
'(polynomial x sparse (4 11) (3 -22) (2 18) (1 -14) (0 7))
'(polynomial x sparse (3 13) (2 -21) (1 3) (0 5))
'(polynomial x sparse (2 1) (1 -2) (0 1))
附上完整的过程
#lang racket
;put get实现
(define *op-table* (make-hash))
(define (put op type proc)
(hash-set! *op-table* (list op type) proc))
(define (get op type)
(hash-ref *op-table* (list op type) #f))
(define *type-coercion* (make-hash))
(define (put-coercion type1 type2 proc)
(hash-set! *type-coercion* (list type1 type2) proc))
(define (get-coercion type1 type2)
(hash-ref *type-coercion* (list type1 type2) #f))
(define (attach-tag type-tag contents)
(cond ((eq? type-tag 'scheme-number) contents)
(else (cons type-tag contents))))
(define (type-tag datum)
(cond ((number? datum) 'scheme-number)
((pair? datum) (car datum))
(else (error "Bad tagged datum -- TYPE-TAG" datum))))
(define (contents datum)
(cond ((number? datum) datum)
((pair? datum) (cdr datum))
(else (error "Bad tagged datum -- CONTENTS" datum))))
(define (apply-generic op . args)
(let ((type-tags (map type-tag args)))
(let ((proc (get op type-tags)))
(if proc
(apply proc (map contents args))
(if (= (length args) 2)
(let ((type1 (car type-tags))
(type2 (cadr type-tags))
(a1 (car args))
(a2 (cadr args)))
(let ((t1->t2 (get-coercion type1 type2))
(t2->t1 (get-coercion type2 type1)))
(cond (t1->t2
(apply-generic op (t1->t2 a1 (variable a2)) a2))
(t2->t1
(apply-generic op a1 (t2->t1 a2 (variable a1))))
(else
(error "No method for these types"
(list op type-tags))))))
(error "No method for these types"
(list op type-tags)))))))
(define (add x y) (apply-generic 'add x y))
(define (sub x y) (apply-generic 'sub x y))
(define (mul x y) (apply-generic 'mul x y))
(define (div x y) (apply-generic 'div x y))
(define (=zero? x) (apply-generic '=zero? x))
(define (remainder-terms a b)
(apply-generic 'remainder-terms a b))
(define (coeff-all-zero? x) (apply-generic 'coeff-all-zero? x))
(define (install-scheme-number-package)
(define (tag x)
(attach-tag 'scheme-number x))
(define (gcd a b)
(if (= b 0)
a
(gcd b (remainder a b))))
(put 'add '(scheme-number scheme-number)
(lambda (x y) (tag (+ x y))))
(put 'sub '(scheme-number scheme-number)
(lambda (x y) (tag (- x y))))
(put 'mul '(scheme-number scheme-number)
(lambda (x y) (tag (* x y))))
(put 'div '(scheme-number scheme-number)
(lambda (x y) (tag (/ x y))))
(put '=zero? '(scheme-number)
(lambda (x) (= x 0)))
(put 'gcd '(scheme-number scheme-number)
(lambda (x y) (gcd x y)))
(put 'make 'scheme-number
(lambda (x) (tag x)))
'done)
(define (make-scheme-number n)
((get 'make 'scheme-number) n))
(define (install-rational-package)
(define (numer x) (car x))
(define (denom x) (cdr x))
(define (make-rat n d)
;;(let ((g (gcd n d)))
;;(cons (/ n g) (/ d g)))
(cons n d)
)
(define (add-rat x y)
(make-rat (add (mul (numer x) (denom y))
(mul (numer y) (denom x)))
(mul (denom x) (denom y))))
(define (sub-rat x y)
(make-rat (sub (mul (numer x) (denom y))
(mul (numer y) (denom x)))
(mul (denom x) (denom y))))
(define (mul-rat x y)
(make-rat (mul (numer x) (numer y))
(mul (denom x) (denom y))))
(define (div-rat x y)
(make-rat (mul (numer x) (denom y))
(mul (denom x) (numer y))))
(define (tag x) (attach-tag ' rational x))
(put 'add '(rational rational)
(lambda (x y) (tag (add-rat x y))))
(put 'sub '(rational rational)
(lambda (x y) (tag (sub-rat x y))))
(put 'mul '(rational rational)
(lambda (x y) (tag (mul-rat x y))))
(put 'div '(rational rational)
(lambda (x y) (tag (div-rat x y))))
(put 'make 'rational
(lambda (n d) (tag (make-rat n d))))
'done)
(define (make-rational n d)
((get 'make 'rational) n d))
(define (install-polynomial-package)
(define (make-poly variable term-list)
(cons variable term-list))
(define (variable p) (car p))
(define (term-list p) (cdr p))
(define (add-poly p1 p2)
(if (same-variable? (variable p1) (variable p2))
(make-poly (variable p1)
(add (term-list p1)
(term-list p2)))
(add-poly p1 (contents (poly->poly (tag p2) (variable p1))))))
(define (sub-poly p1 p2)
(if (same-variable? (variable p1) (variable p2))
(make-poly (variable p1)
(sub (term-list p1)
(term-list p2)))
(sub-poly p1 (contents(poly->poly (tag p2) (variable p1))))))
(define (mul-poly p1 p2)
(if (same-variable? (variable p1) (variable p2))
(make-poly (variable p1)
(mul (term-list p1)
(term-list p2)))
(mul-poly p1 (contents(poly->poly (tag p2) (variable p1))))))
(define (div-poly p1 p2)
(if (same-variable? (variable p1) (variable p2))
(make-poly (variable p1)
(div (term-list p1)
(term-list p2)))
(div-poly p1 (contents(poly->poly (tag p2) (variable p1))))))
(define (=zero-poly? poly)
(coeff-all-zero? (term-list poly)))
(define (gcd-poly p1 p2)
(if (same-variable? (variable p1) (variable p2))
(make-poly (variable p1)
(gcd (term-list p1)
(term-list p2)))
(gcd-poly p1 (contents(poly->poly (tag p2) (variable p1))))))
(define (tag p) (attach-tag 'polynomial p))
(put 'gcd '(polynomial polynomial)
(lambda (p1 p2) (tag (gcd-poly p1 p2))))
(put 'add '(polynomial polynomial)
(lambda (p1 p2) (tag (add-poly p1 p2))))
(put 'mul '(polynomial polynomial)
(lambda (p1 p2) (tag (mul-poly p1 p2))))
(put 'sub '(polynomial polynomial)
(lambda (p1 p2) (tag (sub-poly p1 p2))))
(put 'div '(polynomial polynomial)
(lambda (p1 p2) (tag (div-poly p1 p2))))
(put 'variable '(polynomial)
(lambda (p) (variable p)))
(put 'term-list '(polynomial)
(lambda (p) (term-list p)))
(put '=zero? '(polynomial) =zero-poly?)
(put 'make 'polynomial
(lambda (var terms) (tag (make-poly var terms))))
'done)
(define (poly->poly p newvar)
;;把这一项的指数部分转化成旧变量的表达式,比如3*x^2转化为系数为1*x^2*y^0的表达式,用来作为新变量的系数。
(define (term-order->poly order oldvar)
(make-polynomial newvar
(make-sparse-terms
(list (make-term 0
(make-polynomial oldvar
(make-sparse-terms
(list (make-term order 1)))))))))
(define (term-coeff->poly coeff)
(cond ((number? coeff) (number->poly coeff newvar))
((eq? (variable coeff) newvar) coeff)
(else (make-polynomial newvar (make-sparse-terms (list (make-term 0 coeff)))))))
(define (term->poly term oldvar)
(mul (term-order->poly (order term) oldvar)
(term-coeff->poly (coeff term))))
(cond ((eq? (variable p) newvar) p)
((empty-terms? (term-list p)) (make-polynomial newvar (make-sparse-terms '())))
((add (term->poly (first-terms (term-list p)) (variable p))
(poly->poly (make-polynomial (variable p) (make-sparse-terms (rest-terms (term-list p)))) newvar)))))
(define (number->poly n var)
(make-polynomial var (make-sparse-terms (list (make-term 0 n)))))
(put-coercion 'scheme-number 'polynomial number->poly)
(define (install-sparse-polynomial-package)
(define (add-terms L1 L2)
(cond ((empty-termlist? L1) L2)
((empty-termlist? L2) L1)
(else
(let ((t1 (first-term L1)) (t2 (first-term L2)))
(cond ((> (order t1) (order t2))
(adjoin-term
t1 (add-terms (rest-terms L1) L2)))
((< (order t1) (order t2))
(adjoin-term
t2 (add-terms L1 (rest-terms L2))))
(else
(adjoin-term
(make-term (order t1)
(add (coeff t1) (coeff t2)))
(add-terms (rest-terms L1)
(rest-terms L2)))))))))
(define (sub-terms L1 L2)
(cond ((empty-termlist? L1) L2)
((empty-termlist? L2) L1)
(else
(let ((t1 (first-term L1)) (t2 (first-term L2)))
(cond ((> (order t1) (order t2))
(adjoin-term
t1 (sub-terms (rest-terms L1) L2)))
((< (order t1) (order t2))
(adjoin-term
(make-term (order t2) (- 0 (coeff t2))) (sub-terms L1 (rest-terms L2))))
(else
(adjoin-term
(make-term (order t1)
(sub (coeff t1) (coeff t2)))
(sub-terms (rest-terms L1)
(rest-terms L2)))))))))
(define (mul-terms L1 L2)
(if (empty-termlist? L1)
(the-empty-termlist)
(add-terms (mul-term-by-all-terms (first-term L1) L2)
(mul-terms (rest-terms L1) L2))))
(define (mul-term-by-all-terms t1 L)
(if (empty-termlist? L)
(the-empty-termlist)
(let ((t2 (first-term L)))
(adjoin-term
(make-term (+ (order t1) (order t2))
(mul (coeff t1) (coeff t2)))
(mul-term-by-all-terms t1 (rest-terms L))))))
(define (div-terms L1 L2)
(if (empty-termlist? L1)
(list (the-empty-termlist) (the-empty-termlist))
(let ((t1 (first-term L1))
(t2 (first-term L2)))
(if (> (order t2) (order t1))
(list (the-empty-termlist) L1)
(let ((new-c (div (coeff t1) (coeff t2)))
(new-o (- (order t1) (order t2))))
(if (=zero? new-c)
(list (the-empty-termlist) L1)
(let ((rest-of-result (div-terms (sub-terms L1 (mul-term-by-all-terms (make-term new-o new-c) L2)) L2)))
(list (adjoin-term (make-term new-o new-c) (car rest-of-result)) (cadr rest-of-result))
)))))))
(define (remainder-terms a b)
(cadr (div-terms a b)))
(define (gcd-factor L1 L2)
(let ((t1 (first-term L1))
(t2 (first-term L2)))
(let ((o1 (order t1))
(o2 (order t2))
(c (coeff t2)))
(expt c (- (+ 1 o1) o2)))))
(define (pseudoremainder-terms a b)
(remainder-terms (mul-term-by-all-terms (make-term 0 (gcd-factor a b)) a) b))
(define (gcd-terms a b)
(if (empty-termlist? b)
a
(let ((reslut (gcd-terms b (pseudoremainder-terms a b))))
(mul-term-by-all-terms (make-term 0 (/ 1 (gcd-coeff-term reslut))) reslut))))
(define (gcd-coeff-term a)
(cond ((= (length a) 1) (coeff (first-term a)))
((null? a) 1)
(else (gcd (coeff (first-term a)) (gcd-coeff-term (rest-terms a))))))
(define (coeff-all-zero? term-list)
(if (empty-termlist? term-list)
#t
(if (=zero? (coeff (first-term term-list)))
(coeff-all-zero? (rest-terms term-list))
#f)))
(define (the-empty-termlist) '())
(define (first-term term-list) (car term-list))
(define (rest-terms term-list) (cdr term-list))
(define (empty-termlist? term-list) (null? term-list))
(define (make-term order coeff) (list order coeff))
(define (order term) (car term))
(define (coeff term) (cadr term))
(define (tag p) (attach-tag 'sparse p))
(put 'coeff-all-zero? '(sparse)
(lambda (p1) (coeff-all-zero? p1)))
(put 'remainder-terms '(sparse sparse)
(lambda (p1 p2) (tag (remainder-terms p1 p2))))
(put 'gcd '(sparse sparse)
(lambda (p1 p2) (tag (gcd-terms p1 p2))))
(put 'add '(sparse sparse)
(lambda (p1 p2) (tag (add-terms p1 p2))))
(put 'mul '(sparse sparse)
(lambda (p1 p2) (tag (mul-terms p1 p2))))
(put 'sub '(sparse sparse)
(lambda (p1 p2) (tag (sub-terms p1 p2))))
(put 'div '(sparse sparse)
(lambda (p1 p2) (tag (div-terms p1 p2))))
(put 'order 'term
(lambda (p) (order p)))
(put 'coeff 'term
(lambda (p) (coeff p)))
(put 'make 'term
(lambda (p t) (make-term p t)))
(put 'rest-terms '(sparse)
(lambda (p) (rest-terms p)))
(put 'empty-terms '(sparse)
(lambda (p) (empty-termlist? p)))
(put 'first-terms '(sparse)
(lambda (p) (first-term p)))
(put 'make 'sparse
(lambda (terms) (tag terms)))
'done)
(define (adjoin-term term term-list)
(if (=zero? (coeff term))
term-list
(cons term term-list)))
(define (variable x)
(apply-generic 'variable x))
(define (term-list x)
(apply-generic 'term-list x))
(define (order term)
((get 'order 'term) term))
(define (coeff term)
((get 'coeff 'term) term))
(define (make-term order coeff)
((get 'make 'term) order coeff))
(define (rest-terms term-list)
(apply-generic 'rest-terms term-list))
(define (first-terms term-list)
(apply-generic 'first-terms term-list))
(define (make-polynomial var terms)
((get 'make 'polynomial) var terms))
(define (make-sparse-terms terms)
((get 'make 'sparse) terms))
(define (empty-termlist? term-list) (null? term-list))
(define (empty-terms? terms)
(apply-generic 'empty-terms terms))
(define (same-variable? v1 v2)
(define (variable? x) (symbol? x))
(and (variable? v1) (variable? v2) (eq? v1 v2)))
(define (gcd p1 p2)
(apply-generic 'gcd p1 p2))
(define (greatest-common-div-divisor p1 p2)
(gcd p1 p2))
(install-scheme-number-package)
(install-rational-package)
(install-polynomial-package)
(install-sparse-polynomial-package)
(define p1 (make-polynomial 'x (make-sparse-terms '((2 1) (1 -2) (0 1)))))
(define p2 (make-polynomial 'x (make-sparse-terms '((2 11) (0 7)))))
(define p3 (make-polynomial 'x (make-sparse-terms '((1 13) (0 5)))))
(define q1 (mul p1 p2))
(define q2 (mul p1 p3))
(mul p1 p2)
(mul p1 p3)
(greatest-common-div-divisor q1 q2)