cg-Cad

Lisp »Tips 'n Tricks »Lisp & prodotti di numeri complessi

Dati due numeri complessi a=a1+a2i, b=b1+b2i, il loro prodotto è un numero complesso c=c1+c2i con c1=a1b1-a2b2, c2=a1b2+a2b1 il cui calcolo comporta 4 moltiplicazioni e due addizioni di numeri reali.
Un algoritmo * permette di diminuire il numero delle moltiplicazioni:

s1=(a1 + a2)(b1 - b2)
s2=a1b2
s3=a2b1
c1=s1+s2-s3
c2=s2+s3

Ecco tre lisp che implementano tale algoritmo nel moltiplicare due numeri complessi, elevare a potenza un numero complesso e disegnare le radici di un'equazione zn-1 con il metodo di Newton.

ZPERZ

;|

    ZPERZ.LSP (C)2005 by Claudio Piccini
    www.cg-cad.com

    Prodotto di due numeri complessi 
    con il metodo di Strassen

|;

(defun c:zperz ( / a1 a2 b1 b2
                   s1 s2 s3 
                   c1 c2
 )
 (setvar "cmdecho" 0)
 (princ "c=a*b con a,b numeri complessi")
 (setq a1 (getreal "\nparte reale di a      : "))
 (setq a2 (getreal "\nparte immaginaria di a: "))
 (setq b1 (getreal "\nparte reale di b      : "))
 (setq b2 (getreal "\nparte immaginaria di b: "))
 (setq s1 (* (+ a1 a2)(- b1 b2)))
 (setq s2 (* a1 b2))
 (setq s3 (* a2 b1))
 (setq c1 (- (+ s1 s2) s3))
 (setq c2 (+ s2 s3))
 (princ "\nc=(")
 (princ c1)
 (princ ")+(")
 (princ c2)
 (princ ")i")
 (setvar "cmdecho" 1)
 (princ)
)
;;;eof

Test del Lisp

Command: zperz
c=a*b con a,b numeri complessi
parte reale di a : 2
parte immaginaria di a: 1
parte reale di b : 1
parte immaginaria di b: -3
c=(5.0)+(-5.0)i

Command: zperz
c=a*b con a,b numeri complessi
parte reale di a : 4
parte immaginaria di a: -1
parte reale di b : 0
parte immaginaria di b: 2
c=(2.0)+(8.0)i

Command: zperz
c=a*b con a,b numeri complessi
parte reale di a : 4
parte immaginaria di a: -1
parte reale di b : 0
parte immaginaria di b: -2
c=(-2.0)+(-8.0)i

Z^N

;|

    Z^N.LSP (C)2005 by Claudio Piccini
    www.cg-cad.com

    Elevamento a potenza di un numero complesso 
    con il metodo di Strassen

|;

(defun c:z^n ( / n i 
                 a1 a2 b1 b2 
                 s1 s2 s3 
                 c1 c2
 )
 (setvar "cmdecho" 0)
 (princ "z^n, z numero complesso, n intero")
 (initget (+ 2 4)) ; non 0, non negativo
 (setq n (getint "\nn [2]? "))
 (if (= n nil)(setq n 2))
 (setq a1 (getreal "\nparte reale di z? "))
 (setq a2 (getreal "\nparte immaginaria di z? "))
 (setq b1 a1)
 (setq b2 a2)
 (setq i 1)
 ; c1=a1+a2i
 ; c2=b1+b2i
 (while (< i n)
  (setq s1 (* (+ a1 a2)(- b1 b2)))
  (setq s2 (* a1 b2))
  (setq s3 (* a2 b1))
  (setq c1 (- (+ s1 s2) s3))
  (setq c2 (+ s2 s3))
  (setq b1 c1)
  (setq b2 c2)
  (setq i (1+ i))
 )
 (princ "\nz^")
 (princ n)
 (princ "=(")
 (princ c1)
 (princ ")+(")
 (princ c2)
 (princ ")i")
 (setvar "cmdecho" 1)
 (princ)
)
;;;eof

Command: z^n
z^n, z numero complesso, n intero
n [2]? 4
parte reale di z? -2
parte immaginaria di z? 2
z^4=(-64.0)+(0.0)i

Command: z^n
z^n, z numero complesso, n intero
n [2]? Invio
parte reale di z? 0
parte immaginaria di z? 2
z^2=(-4.0)+(0.0)i

NEWTN

;|

    NEWTN.LSP (C)2005 by Claudio Piccini
    www.cg-cad.com

|;

(defun zpown ( a1 a2 n / i b1 b2 s1 s2 s3 )
 (setq i 1)
 (setq b1 a1)
 (setq b2 a2)
 ; c1=a1+a2i
 ; c2=b1+b2i
 (while (< i n)
  (setq s1 (* (+ a1 a2)(- b1 b2)))
  (setq s2 (* a1 b2))
  (setq s3 (* a2 b1))
  (setq c1 (- (+ s1 s2) s3))
  (setq c2 (+ s2 s3))
  (setq b1 c1)
  (setq b2 c2)
  (setq i (1+ i))
 )
)

(defun metodo_newton ( / i j w nc colore
                         x0 y0 x y
                         aa bb cc dd ff gg e 
 )
 (setq i 0)
 (while (< i dim)
  (setq j 0)
  (while (< j dim)
   (setq x (+ -2 (/ (* i 4.0) dim)))
   (setq y (+ -2 (/ (* j 4.0) dim)))
   (setq x0 x)
   (setq y0 y)
   (setq nc 0)   
   (setq w 1)
   (while (<= w steps)
    (zpown x y n)       ; z^n
    (setq aa c1)
    (setq aa (- aa 1))
    (setq bb c2)
    (zpown x y (- n 1)) ; z^(n-1)
    (setq cc c1)
    (setq dd c2)
    (setq cc (* n cc))  ; parte reale di n(z^(n-1))
    (setq dd (* n dd))  ; parte imm. di n(z^(n-1))
    (setq e (+ (* cc cc)(* dd dd)))
    (if (= e 0)(setq e eps)(setq e (/ 1.0 e)))
    (setq ff (+ (* aa cc)(* bb dd)))
    (setq ff (* ff e))
    (setq gg (- (* bb cc)(* aa dd)))
    (setq gg (* gg e))
    (setq x (- x ff))
    (setq y (- y gg))
    (if (and (< (abs (- x x0)) eps)(< (abs (- y y0)) eps))
     (setq w (+ steps 1))
    )
    (setq x0 x)
    (setq y0 y)
    (setq w (1+ w))
    (setq nc (1+ nc))
   )
   (if (= (rem nc 2) 0)
    (setq colore 7)
    (setq colore 1)
   )
   (command "_color" colore)
   (command "_point" (list (+ i (car p0))(+ j (cadr p0))))
   (setq j (1+ j))
  )
  (setq i (1+ i))
 )
)

(defun c:newtn ( / snapp
                   steps eps 
                   n dim p0
                   c1 c2
 )
 (setq steps 30)
 (setq eps 0.0000000001)
 (setvar "cmdecho" 0)
 (setq snapp (getvar "osmode"))
 (command "_osnap" "_non")
 (initget (+ 2 4)) ; non 0, non negativo
 (setq n (getint "\npotenza [3]: "))
 (if (= n nil)(setq n 3))
 (initget (+ 2 4)) ; non 0, non negativo
 (setq dim (getint "\nnumero punti per lato mappa [100]: "))
 (if (= dim nil)(setq dim 100))
 (setq p0 (getpoint "\nseleziona un punto nel disegno..."))
 (metodo_newton)
 (setvar "osmode" snapp)
 (command "_color" "BYLAYER")
 (command "_redraw")
 (setvar "cmdecho" 1)
 (princ)
)
;;;eof

NEWTN.LSPz^3-1

NEWTN.LSPz^6-1

NEWTN.LSPz^21-1



Per approfondire:

(*) Algoritmo di Strassen (1972), in Analisi numerica, V. Comincioli - 1995, McGraw-Hill.

Lisp »Tips 'n Tricks

Ultimo Aggiornamento_Last Update: 6 Giugno 2005