(Lispex)sicp.io
2.11 · Multiple representations for complex numbers

One complex number can keep two useful coordinate systems.

Rectangular contents make addition direct, polar contents make multiplication direct, and one tagged selector interface lets client code observe either representation as the same abstract complex number.

Guiding question

How can one complex-number interface preserve the advantages of rectangular and polar representations at the same time?

  • Construct rectangular contents from real and imaginary parts
  • Construct polar contents from magnitude and angle
  • Dispatch common selectors through a representation tag
  • Use rectangular coordinates for addition and polar coordinates for multiplication
  • Compare inexact trigonometric observations with an explicit tolerance

A rectangular object stores x and y, so real-part and imag-part are direct while magnitude and angle are computed. A polar object stores r and a, so magnitude and angle are direct while real-part and imag-part are computed. The outer tag is a representation fact; it is not part of the abstract complex value seen by client code.

The first program constructs 3 + 4i in both forms and asks the same four selectors to observe them. close? records that the inexact trigonometric path agrees within a stated tolerance. The second program adds through real and imaginary parts and deliberately returns a rectangular object, while multiplication combines magnitudes and angles and returns a polar object. Generic selectors verify the abstract results without exposing either object’s contents to the caller.

Lispex · SICP sourceScheme-compatible SICP syntax executed by the Lispex SICP profile.
(begin
  (define (square x) (* x x))
  (define (close? left right)
    (< (abs (- left right)) 0.000001))
  (define (attach-tag type contents) (cons type contents))
  (define (type-tag object) (car object))
  (define (contents object) (cdr object))
  (define (make-from-real-imag x y)
    (attach-tag 'rectangular (list x y)))
  (define (make-from-mag-ang magnitude angle)
    (attach-tag 'polar (list magnitude angle)))
  (define (rectangular-real z) (car z))
  (define (rectangular-imag z) (cadr z))
  (define (rectangular-magnitude z)
    (sqrt (+ (square (rectangular-real z))
             (square (rectangular-imag z)))))
  (define (rectangular-angle z)
    (atan (rectangular-imag z) (rectangular-real z)))
  (define (polar-magnitude z) (car z))
  (define (polar-angle z) (cadr z))
  (define (polar-real z)
    (* (polar-magnitude z) (cos (polar-angle z))))
  (define (polar-imag z)
    (* (polar-magnitude z) (sin (polar-angle z))))
  (define (select object rectangular-selector polar-selector)
    (cond ((eq? (type-tag object) 'rectangular)
           (rectangular-selector (contents object)))
          ((eq? (type-tag object) 'polar)
           (polar-selector (contents object)))
          (else (error "unknown complex representation"))))
  (define (real-part z) (select z rectangular-real polar-real))
  (define (imag-part z) (select z rectangular-imag polar-imag))
  (define (magnitude z)
    (select z rectangular-magnitude polar-magnitude))
  (define (angle z) (select z rectangular-angle polar-angle))
  (define rectangular (make-from-real-imag 3.0 4.0))
  (define polar (make-from-mag-ang 5.0 (atan 4.0 3.0)))
  (list (type-tag rectangular)
        (type-tag polar)
        (close? (real-part rectangular) (real-part polar))
        (close? (imag-part rectangular) (imag-part polar))
        (close? (magnitude rectangular) (magnitude polar))
        (close? (angle rectangular) (angle polar))))
Lispex learning runtimeLispex SICP profile 1.0.0
Loading Lispex SICP runtime
Lispex · SICP source1,914 / 1,048,576 UTF-8 bytes
Examples
Result
Output
Value
Diagnostic
Visible execution0 / 0 trace events
    This browser result is not a Lispex Vouch record or authority.wasm —
    Expected observation

    The first program returns (rectangular polar #t #t #t #t). The second returns (rectangular polar #t #t #t #t #t #t).

    Trace focus

    Follow the outer type tag before each selector chooses rectangular or polar contents. In the first run, compare direct selectors with the sqrt, atan, sin, and cos path. In the second, notice that addition constructs rectangular contents while multiplication constructs polar contents, then watch the same generic selectors verify both results. The tolerance describes these finite inexact calculations and is not an equality proof for arbitrary numeric programs.

    Try it yourself

    Change the program before you read the hint.

    Represent -3 + 4i in both forms using magnitude 5 and angle (atan 4.0 -3.0). Reuse close? to verify all four selectors, then explain why the two-argument atan matters outside the first quadrant.

    Show one hint

    The signs of both coordinates determine the quadrant. A one-argument atan of y divided by x loses that distinction.