Nombres complexes B: avec struct Cmplx

Description

Bonjour,

Voici un ensemble de fonctions basées sur les nombres complexes définies par "struct Cmplx {...}".

Les "algorithmes" utilisés dans de cette structure sont plus ou moins classiques.
Ils s'appuient sur les formules suivantes:
Forme
  algébrique: z = a + i·b, avec i² = -1
  polaire: z = ρ·(cosθ + i·sinθ), avec ρ = √(a² + b²), cosθ = a/ρ, sinθ = b/ρ
  exponentielle: z = ρ·eⁱᶿ

double
  real(z) = a = partie réelle
  imag(z) = b = partie imaginaire
  norm(z) = a² + b² = carré de la valeur absolue
  abs(z)  = |z| = ρ = √(a² + b²) = module = valeur absolue
  arg(z)  = argument = phase = θ; cosθ = a/ρ, sinθ = b/ρ

Cmplx
  conj(z)    = z̅ = [a - i·b] = complexe conjugué   
  cos(z)     = [cos(a)*cosh(b) - i·sin(a)*sinh(b)]
  cosh(z)    = [cosh(a)*cos(b) + i·sinh(a)*sin(b)]
  exp(z)     = [eᵃ*cos(b) + i·eᵃ*sin(b)]
  log(z)     = [log(abs(z)) + i·2*atan2(b,a+abs(z))]
  log10(z)   = log(z)/log(10)
  polar(ρ,θ) = [ρ*cos(θ) + i·ρ*sin(θ)]
  pow(z,d)   = exp(d*log(z))
  pow(z,z')  = exp(z'*log(z))
  sin(z)     = [sin(a)*cosh(b) + i·cos(a)*sinh(b)]
  sinh(z)    = [sinh(a)*cos(b) + i·cosh(a)*sin(b)]
  sqrt(z)    = [b/y - i·y/2], avec y = sqrt(2*(abs(z)-a))
  tan(z)     = sin(z)/cos(z)
  tanh(z)    = inh(z)/cosh(z)

Description et codes de la structure Cmplx:
#define Reel double

struct Cmplx {
  Reel R,I; // R: partie réelle, I: partie imaginaire

  // -------------- constructeurs
  Cmplx() {R=0.0; I=0.0;} // default
  Cmplx(Reel rl,Reel im) {R=rl; I=im;}
  Cmplx(const Cmplx& z) {R=z.R; I=z.I;}

  // -------------- affectation
  Cmplx& operator=(const Reel rl) {R=rl; I=0.0; return *this;}

  // -------------- affectations avec opération (Cmplx)
  Cmplx& operator+=(const Cmplx& z) {R+=z.R; I+=z.I; return *this;}
  Cmplx& operator-=(const Cmplx& z) {R-=z.R; I-=z.I; return *this;}
  Cmplx& operator*=(const Cmplx& z) {Reel r=R; R=r*z.R-I*z.I; I=r*z.I+I*z.R; return *this;}
  Cmplx& operator/=(const Cmplx& z) {Reel r=R,a=z.R,b=z.I,m=a*a+b*b; R=(r*a+I*b)/m; I=(I*a-r*b)/m; return *this;}

  // -------------- affectations avec opération (Reel)
  Cmplx& operator+=(const Reel d) {R+=d; return *this;}
  Cmplx& operator-=(const Reel d) {R-=d; return *this;}
  Cmplx& operator*=(const Reel d) {R*=d; I*=d; return *this;}
  Cmplx& operator/=(const Reel d) {R/=d; I/=d; return *this;}
};

// -------------- fonctions réelles standards
Reel real(const Cmplx& z) {return z.R;}
Reel imag(const Cmplx& z) {return z.R;}
Reel norm(const Cmplx& z) {return z.R*z.R+z.I*z.I;}
Reel abs (const Cmplx& z) {return sqrt(norm(z));}
Reel arg (const Cmplx& z) {return atan2(z.I,z.R);} // -pi .. +pi radians

// -------------- opérateurs de comparaison
bool operator==(const Cmplx y,const Cmplx& z) {return y.R==z.R && y.I==z.I;}
bool operator!=(const Cmplx y,const Cmplx& z) {return y.R!=z.R || y.I!=z.I;}

// -------------- opérateurs unaires
Cmplx operator+(const Cmplx& z) {return z;}
Cmplx  operator-(const Cmplx& z) {return Cmplx(-z.R,-z.I);}

// -------------- opérateurs binaires
Cmplx& operator+(Cmplx y,const Cmplx& z) {return y+=z;}
Cmplx& operator+(const Reel a,Cmplx z) {return z+=a;}
Cmplx& operator+(Cmplx z,const Reel a) {return z+=a;}
Cmplx& operator-(Cmplx y,const Cmplx& z) {return y-=z;}
Cmplx  operator-(const Reel a,const Cmplx& z) {return Cmplx(a-z.R,a-z.I);}
Cmplx& operator-(Cmplx z,const Reel a) {return z-=a;}
Cmplx& operator*(Cmplx y,const Cmplx& z) {return y*=z;}
Cmplx& operator*(const Reel a,Cmplx z) {return z*=a;}
Cmplx& operator*(Cmplx z,const Reel a) {return z*=a;}
Cmplx& operator/(Cmplx y,const Cmplx& z) {return y/=z;}
Cmplx  operator/(Reel a,const Cmplx& z) {a/=norm(z); return Cmplx(a*z.R,-a*z.I);}
Cmplx& operator/(Cmplx z,const Reel a) {return z/=a;}

// -------------- fonctions complexes  standards
Cmplx conj(const Cmplx& z) {return Cmplx(z.R,-z.I);}
Cmplx cos (const Cmplx& z) {return Cmplx(cos(z.R)*cosh(z.I),-sin(z.R)*sinh(z.I));}
Cmplx cosh(const Cmplx& z) {return Cmplx(cosh(z.R)*cos(z.I),sinh(z.R)*sin(z.I));}
Cmplx exp (const Cmplx& z) {Reel e=exp(z.R); return Cmplx(e*cos(z.I),e*sin(z.I));}
Cmplx log (const Cmplx& z) {Reel m=abs(z); return Cmplx(log(m),2*atan2(z.I,z.R+m));}
Cmplx log10(const Cmplx& z) {return log(z)/=log(10);}
Cmplx polar(const Reel r,const Reel t) {return Cmplx(r*cos(t),r*sin(t));}
Cmplx pow (const Cmplx& z,Reel d) {return exp(log(z)*=d);}
Cmplx pow (const Cmplx& z,const Cmplx& x) {return exp(log(z)*=x);}
Cmplx sin (const Cmplx& z) {return Cmplx(sin(z.R)*cosh(z.I),cos(z.R)*sinh(z.I));}
Cmplx sinh(const Cmplx& z) {return Cmplx(sinh(z.R)*cos(z.I),cosh(z.R)*sin(z.I));}
Cmplx sqrt(const Cmplx& z) {Reel y=sqrt(2*(abs(z)-z.R)); return Cmplx(z.I/y,y/2);}
Cmplx tan (const Cmplx& z) {return sin(z)/=cos(z);}
Cmplx tanh(const Cmplx& z) {return sinh(z)/=cosh(z);}

// -------------- fonctions complexes suplémentaires
Cmplx& square(const Cmplx& z) {return Cmplx(z.R*z.R-z.I*z.I,2*z.R*z.I);}
Cmplx& cube  (const Cmplx& z) {Reel a=z.R,aa=a*a,b=z.I,bb=b*b; return Cmplx(a*aa-3*a*bb,3*aa*b-b*bb);}

Les fonctions square(z) et cube(z) ont été ajoutées pour leur rapidité: en effet, les appels à pow(z,2) ou pow(z,3) sont bien plus "lourds".

Comme il n'y a pas de protection des éléments d'une structure, les fonctions real(z) et imag(z) ne sont pas strictement nécessaires.
A la place, on peut directement utiliser z.R et z.I.

Compilez le fichier CmplxStruct.cpp du Zip; son exécution donne:
Nombres complexes B: avec struct Cmplx

A: x = [-5+i·4], y = [3+i·2.1], z = [7-i·4.88]
B: w=17 = [17+i·0], w = z = [7-i·4.88]
C: x==y ? false, x!=y ? true
D: +z = [7-i·4.88], -z = [-7+i·4.88]
E: x+y = [-2+i·6.1]; w=z, w+=x = [2-i·0.88]; w=z, w+=6 = [13-i·4.88]
E': 3+x = [-2+i·4], x+4 = [-1+i·4]
F: x-y = [-8+i·1.9]; w=z, w-=x = [12-i·8.88]; w=z, w-=6 = [1-i·4.88]
F': 3-x = [8-i·4], x-1 = [-6+i·4]
G: x*y = [-23.4+i·1.5]; w=z, w*=x = [-15.48+i·52.4]; w=z, w*=6 = [42-i·29.28]
G': 3*x = [-15+i·12], x*4 = [-20+i·16]
H: x/y = [-0.49217+i·1.67785]; w=z, w/=x = [-1.32976-i·0.0878049]; w=z, w/=6 = [1.16667-i·0.813333]
H': 3/x = [-0.365854-i·0.292683], x/2.5 = [-2+i·1.6]
I': 3+1/x+z/y-5*x*y = [120.68-i·9.78548]
J: norm(z) = 72.8144, abs(z) = 8.53314, arg(z) = -0.608806
K: conj(z) = [7+i·4.88]
L: cos(z) = [49.6212+i·43.2373], cosh(z) = [91.4743+i·540.632]
M: exp(z) = [182.948+i·1081.27]
N: log(z) = [2.14396-i·0.608806], log10(z) = [0.931109-i·0.264401]
O': polar(5, pi/6) = [4.33013+i·2.5]
P: pow(z, 3) = [-157.102-i·601.146], pow(z, 1.5) = [15.2354-i·19.7286], pow(z, x) = [0.000147522-i·0.00020478]
Q: sin(z) = [43.2423-i·49.6155], sinh(z) = [91.4741+i·540.633]
R: w = sqrt(z) = [-2.78686+i·0.875539], w*w = [7-i·4.88]
S: tan(z) = [0.000114343-i·0.999984], tanh(z) = [1+i·5.47112e-07]
T: square(z) = [25.1856-i·68.32], pow(z,2) = [25.1856-i·68.32]
U: cube(z) = [-157.102-i·601.146], pow(z,3) = [-157.102-i·601.146]

Equation du second degre a coefficients complexes:  a*x*x + b*x + c = 0.
Avec a = [-5+i·4], b = [6+i·3], c = [1-i·7]
  b*b = [27+i·36], 4*a*c = [92+i·156], b*b - 4*a*c = [-65-i·120]
  posons D = b*b - 4*a*c = [-65-i·120], srD = sqrt(D) = [-5.97802+i·10.0368]
  x1 = (-b + srD)/(2*a) = [1.07362+i·0.155222]
  x2 = (-b - srD)/(2*a) = [-0.6346+i·0.795997]
Control 1: a*x1*x1 + b*x1 + c = [-1.77636e-15-i·8.88178e-16]
Control 2: a*x2*x2 + b*x2 + c = [0-i·1.77636e-15]
Comparez ces résultats avec ceux de l'article précédant "Nombres complexes A: ...".

Cette fois, nous pouvons calculer le discriminant b*b - 4*a*c directement !

D'éventuels bugs sont toujours possibles: s'il vous plait, signalez-les moi. Merci d'avance.

Dans le prochain article, les nombres complexes seront basés sur une classe qui permet de "protéger" certains éléments.
 
Bonne lecture ...
 

Liens

CodeS-SourceS: Nombres complexes A: avec la bibliothèque logicielle std complex
CodeS-SourceS: Nombres complexes ( c++, classe )
CodeS-SourceS: Nombres complexes - complex numbers
WikipédiA: Nombre complexe
ism: NOMBRES COMPLEXES.pdf
EasyCalculation: Complex Number Calculator
 

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.