Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

SNIPPET $ICALC : CALCUL COMPLEXE


Information sur la source

Catégorie :AddOns Niveau : Initié Date de création : 18/08/2004 Date de mise à jour : 19/08/2004 02:13:01 Vu : 3 570

Note :
9,75 / 10 - par 4 personnes
9,75 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (12)
Ajouter un commentaire et/ou une note

Description

$calc permet de calculer des expressions réelles uniquement ce qui limite le champ d'action pour des applications graphiques par exemple ...
Après avoir vu maints bidouillages pour simuler des complexes , en avoir fait moi même , voici ce snippet permettant de réaliser des calculs complexes sous mirc (il utilise $calc seulement pour les calculs élémentaires)
 

Source

  • /*
  • $Icalc(expr.) -> calcul d'une expression mathématique complexe
  • Entrée : expression pouvant contenir :
  • - des nombres complexes sous la forme a+ib (ce qui inclut les expressions qu'on calcule avec $calc , modulo une entrée "valide" , certains remplacements tordus de $calc en particulier ne sont pas gérés > renvoient 0)
  • - a|b , qui signifie "(a+ib)" (et non "a+ib"...) comme ils sont traités en interne
  • Lors d'erreurs, l'alias renvoie un résultat (intermédiaire ou final) égal à 0, ce qui correspond au choix (très) discutable fait dans $calc
  • Exemple : calcul de 2 * (1-i)
  • //Echo -a › $Icalc(2 * (1-i))
  • -> renvoie 2|-2
  • //Echo -a › $Icalc(2|0 * (1-i))
  • -> renvoie 2|-2
  • //Echo -a › $Icalc(2|0*1|-1)
  • -> renvoie 2|-2
  • //Echo -a › $Icalc(2|0*1|-1).n
  • -> "natural" , même si c'est assez peu manipulable... -> renvoie 2-2i
  • //Echo -a › $Icalc(2*1|-1).exp
  • -> "exponentiel" , retourne le résultat sous la forme Module|Argument -> renvoie 2.828427|-0.785398
  • //Echo -a › $Icalc(2*1|-1).arg
  • -> "argument" , retourne l'argument du résultat dans l'intervalle ]-Pi;Pi] -> renvoie -0.785398
  • //Echo -a › $Icalc(2*1|-1).mod
  • -> "module" , retourne le module résultat -> renvoie 2.828427
  • Le parsing s'effectue a priori comme $calc , en suivant les règles usuelles de priorité (ordre : ^,%,* et /,+ et -)
  • /itest <expr.> permet de dénicher des bugs sur des expressions REELLES (premier résultat : parsing avec $Icalc , deuxième $calc(expr.)) , si vous en trouvez n'hésitez pas , même si j'ai réussi à me convaincre qu'il y en avait certainement peu :
  • Ex : /itest 9*1000-5*(.1456 -(1-5*(2+9*-7-90)*-2334.546))-0.1164*2+4*9.
  • */
  • Alias Icalc {
  • if (!$isid) return
  • if ($prop == t) { var %s $1 }
  • else {
  • if $2 { echo -s * Too many parameters: $Icalc | return 0 }
  • var %s = $replace($1,$chr(32),,++,+,--,+,-+,-,+-,-)
  • ;erreurs de parenthèses : comme $calc
  • if ($count(%s,$chr(40)) > $count(%s,$chr(41))) { return 0 }
  • if ($count(%s,$chr(40)) < $count(%s,$chr(41))) { var %i 1,%s2 | while ($count(%s2,$chr(40)) >= $count(%s2,$chr(41))) { inc %i | %s2 = $left(%s,%i) } | %s = $left(%s2,-1) }
  • ;retrait des parenthèses et vérification : nombres et opérateurs enchevêtrés comme il faut
  • if !$regex($remove(%s,$chr(40),$chr(41)),/^((-|\+)?[0-9i.|]+[-+*/^%])*(-|\+)?[0-9i.|]+$/i) { return 0 }
  • ;remplacement des opérateurs , élimination des "+" inutiles (début d'expression notamment) , formatage a > a|0 et ib ou bi > 0|b
  • var %mask /([0-9i).])([-+*/^%])/g , %x = $regsub(%s,%mask,\1;o\2;,%s) , %x = $regsub($replace(%s,$chr(40),$chr(40) $+ ;,$chr(41),; $+ $chr(41)),/([-0-9.]+i|i[-0-9.]+)/gi,i0|\1,%s) , %mask /(^|;)([-0-9.]+)(;|$)/g , %x = $regsub(%s,%mask,\1\2|0\3,%s) , %s = $replace($+(;,%s,;),;;,;,;i;,;0|1;,|-i;,|-1;,i,)
  • ;remplacement des parenthèses dans l'ordre (de l'intérieur à l'extérieur)
  • var %m /\(([^()]+)\)/
  • while $regex(%s,%m) { %s = $replace(%s,$+($chr(40),$regml(1),$chr(41)),$Icalc-($regml(1))) }
  • }
  • ;on a des expressions sans parenthèse , on calcul en respectant les priorités des opérateurs ( ^ , % , *|/ , +|- )
  • var %op \^;%;(?:\*|\/);(?:\+|-) , %i 1
  • while $gettok(%op,%i,59) {
  • var %m = /(;([^;]+);o( $+ $v1 $+ );([^;]+);)/
  • while $regex(%s,%m) {
  • %s = $replace(%s,$regml(1),$+(;,$Icalc--($regml(2),$regml(4),$regml(3)),;)) }
  • inc %i
  • }
  • %s = $remove(%s,;)
  • if ($gettok(%s,3,124) != $null) { return 0 }
  • if ($prop == n) { return $replace($+($1,+,$2,i),+-,-) }
  • if ($prop == exp) { return $Itr(%s) }
  • if ($prop == arg) { return $Iarg(%s) }
  • if ($prop == mod) { return $Imod(%s) }
  • return %s
  • }
  • ;récurrence (remplacement des parenthèses , déjà traitées ($prop -> t)
  • Alias -l Icalc- return $Icalc($1).t
  • ;opérations (vues les erreurs d'arrondis grossières de $calc on ne passe pas à la forme exponentielle pour les calculs de puissances)
  • Alias -l Icalc-- {
  • tokenize 124 $+($1,$chr(124),$2,$chr(124),$3)
  • if ($5 == ^) { if ($4) || ((- isin $3) && (!$1) && (!$2)) { return 0|0 } | var %m = $iif(- isin $3,1/,1*) , %3 = $remove($3,-) | return $iif($2,$iif(. isin %3,0|0,$iif(%3,$Icalc(%m $Iexpo($+($1,$chr(124),$2),%3)),1|0)),$calc($1 ^ $3) $+ |0) }
  • if ($5 == %) { if ($2) || (!$3) || ($4) { return 0|0 } | return $calc($1 % $3) $+ |0 }
  • if ($5 == *) { return $+($calc($1 * $3 - $2 * $4),$chr(124),$calc($1 * $4 + $2 * $3)) }
  • if ($5 == /) { var %q $calc($3 ^ 2 + $4 ^ 2) | return $+($calc(($1 * $3 + $2 * $4) / %q),$chr(124),$calc(($2 * $3 - $1 * $4) / %q)) }
  • if ($5 == +) { return $calc($1 + $3) $+ $chr(124) $+ $calc($2 + $4) }
  • if ($5 == -) { return $calc($1 - $3) $+ $chr(124) $+ $calc($2 - $4) }
  • }
  • ;module
  • Alias Imod { tokenize 124 $1 | return $sqrt($calc($1 ^ 2 + $2 ^ 2)) }
  • ;argument
  • Alias Iarg { tokenize 124 $1 | var %m $sqrt($calc($1 ^ 2 + $2 ^ 2)) | return $iif(!%m,0,$+($iif(- isin $2,-),$acos($calc($1 / %m)))) }
  • ;a + i b -> |z| exp(i teta)
  • Alias Itr { tokenize 124 $1 | var %m $sqrt($calc($1 ^ 2 + $2 ^ 2)) | return $iif(!%m,0|0,$+(%m,$chr(124),$iif(- isin $2,-),$acos($calc($1 / %m)))) }
  • ;|z| exp(i teta) -> a + i b
  • Alias Itr2 { tokenize 124 $1 | return $iif(- isin $1,0|0,$calc($1 * $cos($2)) $+ $chr(124) $+ $calc($1 * $sin($2))) }
  • ;exponentielle complexe (utile pour les rotations ...) > exemple $iexp($pi / 2)
  • Alias Iexp { return $cos($calc($1)) $+ $chr(124) $+ $sin($calc($1)) }
  • ;"exponentiation rapide"
  • Alias -l Iexpo return $iif($2 == 1, $1 , $iif(2 // $2, $Icalc($Iexpo2($1,$calc($2 /2)) * $Iexpo2($1,$calc($2 /2))) , $Icalc($1 * $Iexpo2($1,$calc(($2 -1)/2)) * $Iexpo2($1,$calc(($2 -1)/2)))))
  • ;un jour mirc supportera les appels récursifs ... en attendant :
  • Alias -l Iexpo2 return $Iexpo($1,$2)
  • ;tests REELS
  • Alias Itest { echo -a › $1- $str($chr(160),10) ¬ Résultats : $Icalc($1-) • $calc($1-) }
/*
$Icalc(expr.) -> calcul d'une expression mathématique complexe
Entrée : expression pouvant contenir :
- des nombres complexes sous la forme a+ib (ce qui inclut les expressions qu'on calcule avec $calc , modulo une entrée "valide" , certains remplacements tordus de $calc en particulier ne sont pas gérés > renvoient 0)
- a|b , qui signifie "(a+ib)" (et non "a+ib"...) comme ils sont traités en interne
Lors d'erreurs, l'alias renvoie un résultat (intermédiaire ou final) égal à 0, ce qui correspond au choix (très) discutable fait dans $calc
Exemple : calcul de 2 * (1-i)
//Echo -a › $Icalc(2 * (1-i)) 
-> renvoie 2|-2
//Echo -a › $Icalc(2|0 * (1-i)) 
-> renvoie 2|-2
//Echo -a › $Icalc(2|0*1|-1) 
-> renvoie 2|-2
//Echo -a › $Icalc(2|0*1|-1).n 
-> "natural" , même si c'est assez peu manipulable... -> renvoie 2-2i
//Echo -a › $Icalc(2*1|-1).exp 
-> "exponentiel" , retourne le résultat sous la forme Module|Argument -> renvoie 2.828427|-0.785398
//Echo -a › $Icalc(2*1|-1).arg 
-> "argument" , retourne l'argument du résultat dans l'intervalle ]-Pi;Pi] -> renvoie -0.785398
//Echo -a › $Icalc(2*1|-1).mod 
-> "module" , retourne le module résultat -> renvoie 2.828427
Le parsing s'effectue a priori comme $calc , en suivant les règles usuelles de priorité (ordre : ^,%,* et /,+ et -)
/itest <expr.> permet de dénicher des bugs sur des expressions REELLES (premier résultat : parsing avec $Icalc , deuxième $calc(expr.)) , si vous en trouvez n'hésitez pas , même si j'ai réussi à me convaincre qu'il y en avait certainement peu :
Ex : /itest 9*1000-5*(.1456 -(1-5*(2+9*-7-90)*-2334.546))-0.1164*2+4*9.
*/

Alias Icalc {
  if (!$isid) return
  if ($prop == t) { var %s $1 }
  else {
    if $2 { echo -s * Too many parameters: $Icalc | return 0 }
    var %s = $replace($1,$chr(32),,++,+,--,+,-+,-,+-,-)
    ;erreurs de parenthèses : comme $calc
    if ($count(%s,$chr(40)) > $count(%s,$chr(41))) { return 0 }
    if ($count(%s,$chr(40)) < $count(%s,$chr(41))) { var %i 1,%s2 | while ($count(%s2,$chr(40)) >= $count(%s2,$chr(41))) { inc %i | %s2 = $left(%s,%i) } | %s = $left(%s2,-1) }
    ;retrait des parenthèses et vérification : nombres et opérateurs enchevêtrés comme il faut
    if !$regex($remove(%s,$chr(40),$chr(41)),/^((-|\+)?[0-9i.|]+[-+*/^%])*(-|\+)?[0-9i.|]+$/i) { return 0 }
    ;remplacement des opérateurs , élimination des "+" inutiles (début d'expression notamment) , formatage a > a|0 et ib ou bi > 0|b
    var %mask /([0-9i).])([-+*/^%])/g , %x = $regsub(%s,%mask,\1;o\2;,%s) , %x = $regsub($replace(%s,$chr(40),$chr(40) $+ ;,$chr(41),; $+ $chr(41)),/([-0-9.]+i|i[-0-9.]+)/gi,i0|\1,%s) , %mask /(^|;)([-0-9.]+)(;|$)/g , %x = $regsub(%s,%mask,\1\2|0\3,%s) , %s = $replace($+(;,%s,;),;;,;,;i;,;0|1;,|-i;,|-1;,i,)
    ;remplacement des parenthèses dans l'ordre (de l'intérieur à l'extérieur)
    var %m /\(([^()]+)\)/
    while $regex(%s,%m) { %s = $replace(%s,$+($chr(40),$regml(1),$chr(41)),$Icalc-($regml(1))) }
  }
  ;on a des expressions sans parenthèse , on calcul en respectant les priorités des opérateurs ( ^ , % , *|/ , +|- )
  var %op \^;%;(?:\*|\/);(?:\+|-) , %i 1
  while $gettok(%op,%i,59) {
    var %m = /(;([^;]+);o( $+ $v1 $+ );([^;]+);)/
    while $regex(%s,%m) {
    %s = $replace(%s,$regml(1),$+(;,$Icalc--($regml(2),$regml(4),$regml(3)),;)) }
    inc %i
  }
  %s = $remove(%s,;)
  if ($gettok(%s,3,124) != $null) { return 0 }
  if ($prop == n) { return $replace($+($1,+,$2,i),+-,-) }
  if ($prop == exp) { return $Itr(%s) }
  if ($prop == arg) { return $Iarg(%s) }
  if ($prop == mod) { return $Imod(%s) }
  return %s
}
;récurrence (remplacement des parenthèses , déjà traitées ($prop -> t)
Alias -l Icalc- return $Icalc($1).t
;opérations (vues les erreurs d'arrondis grossières de $calc on ne passe pas à la forme exponentielle pour les calculs de puissances)
Alias -l Icalc-- {
  tokenize 124 $+($1,$chr(124),$2,$chr(124),$3)
  if ($5 == ^) { if ($4) || ((- isin $3) && (!$1) && (!$2)) { return 0|0 } | var %m = $iif(- isin $3,1/,1*) , %3 = $remove($3,-) | return $iif($2,$iif(. isin %3,0|0,$iif(%3,$Icalc(%m $Iexpo($+($1,$chr(124),$2),%3)),1|0)),$calc($1 ^ $3) $+ |0) }
  if ($5 == %) { if ($2) || (!$3) || ($4) { return 0|0 } | return $calc($1 % $3) $+ |0 }
  if ($5 == *) { return $+($calc($1 * $3 - $2 * $4),$chr(124),$calc($1 * $4 + $2 * $3)) }
  if ($5 == /) { var %q $calc($3 ^ 2 + $4 ^ 2) | return $+($calc(($1 * $3 + $2 * $4) / %q),$chr(124),$calc(($2 * $3 - $1 * $4) / %q)) }
  if ($5 == +) { return $calc($1 + $3) $+ $chr(124) $+ $calc($2 + $4) }
  if ($5 == -) { return $calc($1 - $3) $+ $chr(124) $+ $calc($2 - $4) }
}
;module
Alias Imod { tokenize 124 $1 | return $sqrt($calc($1 ^ 2 + $2 ^ 2)) }
;argument
Alias Iarg { tokenize 124 $1 | var %m $sqrt($calc($1 ^ 2 + $2 ^ 2)) | return $iif(!%m,0,$+($iif(- isin $2,-),$acos($calc($1 / %m)))) }
;a + i b -> |z| exp(i teta)
Alias Itr { tokenize 124 $1 | var %m $sqrt($calc($1 ^ 2 + $2 ^ 2)) |  return $iif(!%m,0|0,$+(%m,$chr(124),$iif(- isin $2,-),$acos($calc($1 / %m)))) }
;|z| exp(i teta) -> a + i b
Alias Itr2 { tokenize 124 $1 | return $iif(- isin $1,0|0,$calc($1 * $cos($2)) $+ $chr(124) $+ $calc($1 * $sin($2))) }
;exponentielle complexe (utile pour les rotations ...) > exemple $iexp($pi / 2)
Alias Iexp { return $cos($calc($1)) $+ $chr(124) $+ $sin($calc($1)) }
;"exponentiation rapide"
Alias -l Iexpo return $iif($2 == 1, $1 , $iif(2 // $2, $Icalc($Iexpo2($1,$calc($2 /2)) * $Iexpo2($1,$calc($2 /2))) , $Icalc($1 * $Iexpo2($1,$calc(($2 -1)/2)) * $Iexpo2($1,$calc(($2 -1)/2)))))
;un jour mirc supportera les appels récursifs ... en attendant :
Alias -l Iexpo2 return $Iexpo($1,$2)
;tests REELS
Alias Itest { echo -a › $1- $str($chr(160),10) ¬ Résultats : $Icalc($1-) • $calc($1-) }

Conclusion

Installation : Clic droit sur la source , Copier , puis allez dans l'éditeur de remotes de mirc et de nouveau clic droit : Coller . Pour vous en servir vous pouvez d'abord tester les exemples de l'en-tête du remote ...

Je suis ouvert à toute remarque en particulier optimisation/bugs/améliorations
Je m'excuse d'avance , non de l'utilité de ces aliases qui n'est pas à démontrer en ce qui me concerne (c'est suffisant) mais du fait que le code soit assez illisible vu l'utilisation outrancière des expressions régulières ... je le poste surtout pour connaître les bugs en fait et si ca intéresse certains ^^"
 

Historique

18 août 2004 03:45:41 :
Faute de frappe dans l'en tête : Exemple : calcul de 2 * (1-i) et non (1+i)
19 août 2004 02:13:02 :
Améliration des puissances : exponentiation rapide

Commentaires et avis

signaler à un administrateur
Commentaire de tofu le 18/08/2004 07:17:11

HaHa ya plein de mecs qui mavaient dit que ct pas possible darriver à exprimer les complexes sous mirc, jsavais bien que ct possible :!
bvo pada §

signaler à un administrateur
Commentaire de ReMi34 le 18/08/2004 10:04:43

Impressionnant !

signaler à un administrateur
Commentaire de Seregon le 18/08/2004 12:14:36

joli bien joué ca sra utile sur d picwin pr d transformation dan le plan ca

signaler à un administrateur
Commentaire de PaDa le 18/08/2004 12:34:26

merci :))
au départ j'avais commencé a refaire $calc réel intégralement (pour éviter les erreurs d'arrondis et au dela de 17 chiffres) mais a raison de qq dixièmes de seconde pour chaque calcul impossible d'en envisager des centaines à la suite.
Au passage dans le snippet j'ai inclus trois aliases permettant de l'utiliser un peu , $itr et $itr2 pour passer de la forme a+ib a la forme exponentielle et inversement , et $iexp qui permettra les rotations dans les picwins justement :P

signaler à un administrateur
Commentaire de Kerrigan le 18/08/2004 16:11:52

tres intéréssant. Bravo je sais pas si tout le monde se rend compte de la prouesse de Pada mais c'est vraiment beau rien a dire.

Maintenant tu nous fait le meme et en calcul formel avec extraction des partie réelles et imaginaires

t'as l'air de pouvoir faire ça. :)

signaler à un administrateur
Commentaire de Kerrigan le 18/08/2004 19:30:44

tiens, une derniere remarque, est ce qu'il serait possible, d'avoir les resultat sous forme "exacte"

genre module = sqrt(réel)
argument = arctan(réel)

ça peut toujours servir, comme ça on se fiche du nombre de décimal limité du mirc.

signaler à un administrateur
Commentaire de PaDa le 18/08/2004 21:27:24

pour le calcul formel , c'est le même principe avec un millier de lignes en plus : en fait je vois pas trop comment faire ca joliment , donc faut rentrer "à la main" dans le code tous les types de simplifications qui peuvent se faire , faire un bout du parser qui fait une distributivité a droite , un a gauche etc ... fastidieux mais en cours =]
pour les résultats sous forme exacte ouép j'rajouterai un truc no pb chu pas chez moi mais j'updaterai bientot en améliorant , ce snippet étant destiné à évoluer . je sais pas si t'as vu les puissances sont pas faites proprement non plus j'ai Z^N = $icalc(Z $str(* Z,N-1)) , l'astuce est cool mais ce n'est pas efficace et ca bloque avec des "line too long" ... j'ferai un truc d'exponentiation rapide cette nuit je pense ...
merci pour ton commentaire en tout cas , pi quand j'aurai bossé plus dessus pourquoi pas l'intégrer a un truc plus grand comme maths.h ? :pppp

signaler à un administrateur
Commentaire de Kerrigan le 19/08/2004 01:02:43

ben entre nous je n'y vois aucun problème. Par contre Math.h c'est plus qu'une librairie, si tu veux l'intégrer, faudra faire les dialogues qui vont avec. A la limite si tu n'es pas chaud question dialogue, je peux toujours les faire, mais il est capitale de faire un dialogue pour joindre la partie purement librairie de ton code.

Sinon ouais je suis d'ac, j'aimerais beaucoup ajouter les polynomes que tu as codé aussi, et la cerise sur la gateau, ça sera la version amélioré de matrice.h associée a math.h . Un projet a suivre donc...

signaler à un administrateur
Commentaire de PaDa le 19/08/2004 01:13:38

un projet  qui s'annonce intéressant :) c'est pas encore assez abouti pour que l'on y pense mais en mixant tout le boulot que t'as déja abbattu et une version améliorée de ce que je viens de faire , une librairie sur les matrices sympo , tout ca pourrait donner un outil ultime pour les maths héhé
To be continued :p

signaler à un administrateur
Commentaire de Kerrigan le 19/08/2004 23:07:49

ben tu me dis quand tu es pres, je t'attends.

signaler à un administrateur
Commentaire de fyltum le 17/10/2004 04:20:23

quelle star ce PaDa j'ai pas compris un mot :) bien joué alors ...

signaler à un administrateur
Commentaire de HeXoR le 27/01/2006 21:25:14

c'est vraiment bon ça bravo... alala ces regex, jamais rien compris moi :P

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,421 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.