begin process at 2010 02 09 20:53:20
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

AddOns

 > SNIPPET $ICALC : CALCUL COMPLEXE

SNIPPET $ICALC : CALCUL COMPLEXE


 Information sur la source

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

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

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

Auteur : PaDa

Ecrire un message privé
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

 Sources du même auteur

Source avec Zip Source avec une capture GEOTOOLS : GESTION D'UN UWORLD
Source avec Zip Source avec une capture FRACTALES EN PICWINS
ASPIRATEUR DE GALERIES INTERNET
Source avec Zip Source avec une capture SCANNER MULTIFONCTIONS
Source avec Zip QUOTEUR (MDX)

 Sources de la même categorie

BLACKLIST PSEUDOS/MASKS par usurpateur
Source avec une capture [XCHAT] ANTI KICK / AWAY C++ par GeroXXXX
JEU DU CODE par alanpersonproject
SERVEUR FTP par hisoka2501
BANNIR LES AGES, LES HOMMES, LES FEMMES ET PSEUDO AVEC CHIFF... par cougar_du_havre

Commentaires et avis

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 §

Commentaire de ReMi34 le 18/08/2004 10:04:43

Impressionnant !

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

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

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. :)

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.

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

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...

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

Commentaire de Kerrigan le 19/08/2004 23:07:49

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

Commentaire de fyltum le 17/10/2004 04:20:23

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

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...

Comparez les prix

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
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

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,390 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales