2.4.1 复数的表示

2.4.1 复数的表示
我们将开发一个系统来执行复数的算术运算,来作一个简单的例子。但是这个非实际使用的例子
也使用了通用性的操作。我们开始讨论用有序数对表示的复数的两种表示形式。平面坐标
(实部和虚部)和极坐标(模和角度)。在2。4。2部分中,将能够看到在使用类型标签和通用性的操作后,
两种表示法是如何共存于一个系统中的。

像有理数一样,复数也能被自然地表示成有序数对。复数的集合能够被看成是有两个坐标轴的两维空间。
一个是实部的坐标轴,一个是虚部的坐标轴。从这个观点来看,复数z=x+iy(i^2=-1)
,能被视作为在平面上实坐标是x,虚坐标是y的一个点。复数据的加法归结为在这种表示法下的坐标的加法。

real-part(c1+c2)=real-part(c1)+real-part(c2)
imaginary-part(c1+c2)=imaginary-part(c1)+imaginary-part(c2)

当乘复数时,用极坐标的方式表示一个复数是更自然的事了。有一个长度和一个角度。(在图2.20中的r和A)
两个复数的乘积是一个向量延伸另一个复数的长度,旋转另一个复数的角度。

Magnitude(c1*c2)=Magnitude(c1)*Magnitude(c2)
Angle(c1*c2)=Angle(c1)+Angle(c2)

因此,对于复数,有两种不同的表示方式,它们分别适合不同的操作。然而从程序员的角度来看,
写一个程序使用复数,数据抽象的原则建议是操作复数的所有的操作应该
可用而无关它的表示方式。例如,能够找到用平面坐标表示的复数的长度是很有用的。
类似的是,能够确定出一个用极坐标表示的复数的实部是很有用的。

   ^
   |
  y|- - -/*  z=x+iy=re^iA
   |    / |
   |  r/  |
   |  /   |
   | /    |
___|/_A____|_________________________________>
   |      x
图2.20  在平面上复数是一个点。


为了设计出这样的系统,我们能够遵循与2.1.1部分中设计有理数程序包的相同的数据抽象的策略。
假定复数上的操作被实现为四个选择子,real-part,imag-part,magnitude,angle.也假定我们有
两个组装复数的程序。make-from-real-imag 程序返回一个有实部和虚部的复数。
make-from-mag-ang返回一个有长度和角度的复数。对于任何一个复数,这些程序满足以下的属性。

(make-from-real-imag (real-part z) (imag-part z))

(make-from-mag-ang (magnitude z) (angle z))
产生的复数都等于z.

使用这些组装子和选择子,我们能够实现在复数上的算术操作。使用组装子和选择子指定的抽象数据,
就如我们在2.1.1部分中对有理数做的那样。正如上面的公式,我们能够加减复数,使用实部和虚部。
而在乘除复数时,使用长度和角度。

(define (add-complex z1 z2)
     (make-from-real-imag (+ (real-part z1) (real-part z2)) (+ (imag-part z1) (imag-part z2)))
)

(define (sub-complex z1 z2)
     (make-from-real-imag (- (real-part z1) (real-part z2)) (- (imag-part z1) (imag-part z2)))
)

(define (mul-complex z1 z2)
     (make-from-mag-ang (* (magnitude z1) (magnitude z2)) (+ (angle z1) (angle z2)))
)

(define (div-complex z1 z2)
     (make-from-mag-ang (/ (magnitude z1) (magnitude z2)) (- (angle z1) (angle z2)))
)

为了完成复数程序包,我们必须选择一种表示方法,我们必须实现选择子和组装子,是用原生的数据和原生的列表结构。
为了实现这个目标,有两个明显的方式。我们能表示一个复数以平面坐标的方式,作为数对来实现,它有实部和虚部。
或者是极坐标的方式,作为数对来实现,它有长度和角度。我们要选择哪一个呢?

由于有两个不同的选择的情况,我们想象有两个程序员,Ben Bitdiddle和Alyssa P.Hacker,他们
独立地设计复数系统的表示方法。Ben Bitdiddle表示复数用平面坐标。 在这种选择下,选择复数的
实部和虚部是很自然的事。正如用给定的实部和虚部来组装复数一样。为了找到长度和角度,或者是用一个给定的
长度和角度来组装一个复数,他使用了如下的三角函数关系:

x=r* cosA      r=sqrt(x^2+y^2)
y=r* sinA      A=arctan(y,x)

上述的公式能把实部和虚部的(x,y)转换成长度和角度的(r,A).Ben的表示由如下的选择子和组装子构成:
(define (real-part z) (car z))
(define (imag-part z) (cdr z))
(define (magnitude z)
      (sqrt (+ (square (real-part z)) (square (imag-part z)))
      )
)

(define (angle z)
      (atan (imag-part z) (real-part z))
)

(define (make-from-real-imag x y) (cons x y))

(define (make-from-mag-ang r a)
    (cons (* r (cos a)) (* r (sin a))
    )
)

Alyssa,是相反的,她选择了用极坐标表示复数。对她而言,选择长度和角度是很自然的事,
但她不得不使用三角函数的关系,得到复数的实部和虚部。Alyssa的表示如下:

(define (real-part z) (* (magnitude z) (cos (angle z))))
(define (imag-part z) (* (magnitude z) (sin (angle z))) )
(define (magnitude z) (car z))
(define (angle z) (cdr z))
(define (make-from-real-imag x y) (cons (sqrt (+ (square x) (square y)))  (atan y x)
) )
(define (make-from-mag-ang r a)
    (cons r a))

数据抽象的原则保证了 add-complex,sub-complex,mul-complex,div-complex的
相同的实现能够正常地工作在Ben的表示方法与Alyssa的表示方式之上。

猜你喜欢

转载自blog.csdn.net/gggwfn1982/article/details/81477328
今日推荐