灯下 登录
计算机科学 / SICP / 2.5.3 Example: Symbolic Algebra

Exercise 2.97 · 习题

Exercise 2.97:

Implement this algorithm as a procedure reduce-terms that takes two term
lists n and d as arguments and returns a list nn,
dd, which are n and d reduced to lowest terms via the
algorithm given above. Also write a procedure reduce-poly, analogous to
add-poly, that checks to see if the two polys have the same variable.
If so, reduce-poly strips off the variable and passes the problem to
reduce-terms, then reattaches the variable to the two term lists
supplied by reduce-terms.

Define a procedure analogous to reduce-terms that does what the original
make-rat did for integers:

(define (reduce-integers n d)
(let ((g (gcd n d)))
(list (/ n g) (/ d g))))

and define reduce as a generic operation that calls apply-generic
to dispatch to either reduce-poly (for polynomial arguments) or
reduce-integers (for scheme-number arguments). You can now
easily make the rational-arithmetic package reduce fractions to lowest terms by
having make-rat call reduce before combining the given numerator
and denominator to form a rational number. The system now handles rational
expressions in either integers or polynomials. To test your program, try the
example at the beginning of this extended exercise:

(define p1
(make-polynomial 'x '((1 1) (0 1))))
(define p2
(make-polynomial 'x '((3 1) (0 -1))))
(define p3
(make-polynomial 'x '((1 1))))
(define p4
(make-polynomial 'x '((2 1) (0 -1))))
(define rf1 (make-rational p1 p2))
(define rf2 (make-rational p3 p4))
(add rf1 rf2)

See if you get the correct answer, correctly reduced to lowest terms.

The GCD computation is at the heart of any system that does

operations on rational functions. The algorithm used above, although

mathematically straightforward, is extremely slow. The slowness is due partly

to the large number of division operations and partly to the enormous size of

the intermediate coefficients generated by the pseudodivisions. One of the

active areas in the development of algebraic-manipulation systems is the design

of better algorithms for computing polynomial GCDs.

练习 2.97:

将上述算法实现为过程 reduce-terms,它以两个项表 n 和 d 作为参数,返回一个表 nn、dd,即按上述算法将 n 和 d 化为最简形式的结果。同时编写过程 reduce-poly,类似于 add-poly,检验两个多项式是否具有相同的变量;若是,reduce-poly 剥去变量后将问题交给 reduce-terms 处理,再将变量重新附到 reduce-terms 所返回的两个项表上。

定义一个类似于 reduce-terms 的过程,完成原来 make-rat 对整数所做的工作:

(define (reduce-integers n d)
(let ((g (gcd n d)))
(list (/ n g) (/ d g))))

并将 reduce 定义为一个通用操作,调用 apply-generic 分派到 reduce-poly(对多项式参数)或 reduce-integers(对 scheme-number 参数)。现在,通过让 make-rat 在将给定分子和分母组合成有理数之前调用 reduce,可以轻松地使有理算术包将分数化为最简形式。系统现在能够处理以整数或多项式表示的有理表达式。为了测试你的程序,请尝试本扩展练习开头的例子:

(define p1
(make-polynomial 'x '((1 1) (0 1))))
(define p2
(make-polynomial 'x '((3 1) (0 -1))))
(define p3
(make-polynomial 'x '((1 1))))
(define p4
(make-polynomial 'x '((2 1) (0 -1))))
(define rf1 (make-rational p1 p2))
(define rf2 (make-rational p3 p4))
(add rf1 rf2)

检验是否得到了正确且已化为最简形式的答案。

多项式 GCD 的计算是任何对有理函数进行操作的系统的核心。上面使用的算法虽然在数学上直截了当,但速度极慢。速度慢的原因一方面是除法操作数量庞大,另一方面是伪除法过程中产生的中间系数规模巨大。设计更好的多项式 GCD 计算算法,是代数操控系统开发中的活跃研究领域之一。