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
|
z^3-1
z^6-1
z^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
|