IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Mutliplication decimal avec complex


Sujet :

Python

  1. #1
    Membre averti
    Inscrit en
    Mars 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 44
    Par défaut Mutliplication decimal avec complex
    Bonjour, j'ai un probleme concernant les operations avec les "Decimal". En fait j'ai besoin d'utiliser "Decimal" pour pouvoir utiliser des nombres tels que exp(1800) par exemple. Mais je ne parvient pas à multiplier un decimal par un complex....Python (V2.4.4) n'accepte pas ce type de multiplication :

    decimal*exp(1j*450) (par exemple)

    Il me dit alors'unsupported operand type(s) for *:'complex' and 'Decimal'


    Kkun aurait il une idee pour multiplier un decimal et un complex???

    MERCI

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Le type complex intégré à python est pratique, parce qu'il permet des calculs de base déjà prévus (addition, multiplication, etc...), et même des calculs plus élaborés avec le module cmath.

    Par contre, créer un nouveau nombre complexe avec des grands nombres type "Decimal" est accepté à condition que la conversion en flottant reste possible:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    z = complex(Decimal("27182818284590452353602874"), Decimal("7"))
    print z
    (2.71828182846e+025+7j)
    Donc, dès que tu utilises le type de donnée complex, ses composantes réelles et imaginaires sont réduites aux flottants.

    Cela veut dire que si tu veux traiter des complexes avec des parties réelles et imaginaire énormes dépassant les limites des flottants (env. 1.0E300), il te reste à les traiter comme des listes x = (reel,imag), et à créer les quelques fonctions de calculs de complexes. Si tu veux aller plus loin, Python permet d'ailleurs pas mal de possibilités pour créer un nouveau type de données sous forme de classe, et pour définir les opérateurs de calculs correspondants.

    Tyrtamos

  3. #3
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Cela veut dire que si tu veux traiter des complexes avec des parties réelles et imaginaire énormes dépassant les limites des flottants (env. 1.0E300), il te reste à les traiter comme des listes x = (reel,imag), et à créer les quelques fonctions de calculs de complexes. Si tu veux aller plus loin, Python permet d'ailleurs pas mal de possibilités pour créer un nouveau type de données sous forme de classe, et pour définir les opérateurs de calculs correspondants.
    Un exemple ? J'aurais voulu créer des quaternions. Si tu montres comment redéfinir les complexes, cela m'aiderait. J'imagine que l'on surclasse et on redéfinit les opérations __add,... etc. C'est bien cela.

  4. #4
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par rambc Voir le message
    Un exemple ? J'aurais voulu créer des quaternions. Si tu montres comment redéfinir les complexes, cela m'aiderait. J'imagine que l'on surclasse et on redéfinit les opérations __add,... etc. C'est bien cela.
    Oui, c'est bien à cela que je pense.

    Voilà un tout petit exemple de création d'un nouveau type de nb complexe:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    class compl(object):
     
        def __init__(self, x, y=0):
            self.x = x
            self.y = y
     
        def __str__(self):
            return "(%s,%si)" % (self.x,self.y)
     
        def __add__(self,autre):
            return self.__class__(self.x+autre.x, self.y+autre.y)
     
        def __mul__(self,autre):
            return self.__class__(self.x*autre.x-self.y*autre.y, self.x*autre.y+self.y*autre.x)
    Utilisation:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    x = compl(1,3)
    print x
    (1,3i)
     
    y = compl(4,7)
    print y
    (4,7i)
     
    print x+y
    (5,10i)
     
    print x*y
    (-17,19i)
    On peut vérifier les résultats avec le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    x = complex(1,3)
    y = complex(4,7)
    print x+y
    print x*y
    Mais bon. Pour traiter le cas complet, il y a du boulot...

    Tyrtamos

  5. #5
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Merci.

  6. #6
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Mais bon. Pour traiter le cas complet, il y a du boulot...
    Je viens de tester cela et c'est effectivement très simple à utiliser. Par contre, pourquoi dis-tu qu'il y a du boulot ?

  7. #7
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour rambc,

    Cela fait du boulot si on veut faire l'intégration complète du nouveau type dans python. Par exemple, je pensais à un nouveau type de nb complexes utilisant uniquement des grands nombres "Decimal()". Si on veut traiter complètement un cas comme celui-là, on peut s'inspirer de toutes les méthodes déjà associées à complex:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    dir(complex)
    ['__abs__', '__add__', '__class__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__eq__', '__float__', '__floordiv__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__int__', '__le__', '__long__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__nonzero__', '__pos__', '__pow__', '__radd__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__rpow__', '__rsub__', '__rtruediv__', '__setattr__', '__str__', '__sub__', '__truediv__', 'conjugate', 'imag', 'real']
    Je pense que certaines méthodes comme __coerce__ ou __float__ permettent d'intégrer les mécanismes de conversion automatiques dans les calculs d'expression python.

    Et il en manque. Par exemple, il manque une méthode "argument()" qui nécessite une fonction de type "atan2" qui n'existe pas dans le module "decimal" et qu'il faut donc refaire...

    On peut aller plus loin en recréant le contenu du module cmath avec les Decimal():

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    dir(cmath)
    ['__doc__', '__name__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cos', 'cosh', 'e', 'exp', 'log', 'log10', 'pi', 'sin', 'sinh', 'sqrt', 'tan', 'tanh']
    Mais bon. Pour traiter un problème ponctuel, il n'est peut-être pas nécessaire d'en faire autant.

    Il n'empêche que cette méthode marche très bien, et que je ne connais pas beaucoup de langages dans lesquels c'est possible aussi facilement...

    Tyrtamos

  8. #8
    Membre averti
    Inscrit en
    Mars 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 44
    Par défaut
    OK donc sa veur dire qu'une solution pour réaliser mes operations est de créer une classe ou je créer le type complex et de définir les différentes opérations dont j'ai besoin????

  9. #9
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Oui et non.

    Créer une classe pour les "grands complexes" permettrait de les utiliser dans des expressions en profitant ainsi que la "machinerie" de python concernant le calcul d'expression.

    Mais pour des besoins limités, comme je l'ai dit plus haut, il est possible de définir une simple liste z=[x,y] pour représenter z=(x+yj). Et fabriquer les différentes fonctions de calcul des complexes en utilisant les nombres du module decimal: compplus(z1,z2), compmoins(z1,z2), compmul(z1,z2), compdiv(z1,z2), etc...

    Mais la difficulté n'est pas de choisir l'une ou l'autre des solutions, mais de constater que pour certains calculs de nb complexes, il manque dans le module décimal toutes les fonctions transcendantes (exp, ln, sin, cos, asin, sinh, cosh, etc...). On n'a à notre disposition dans le module decimal de la version 2.4 que la puissance (power) et la racine carrée (sqrt).

    Or, tu veux calculer l'exponentiel d'un nombre complexe. Tu ne peux pas utiliser le "exp" de cmath, puisque le module cmath ne calcule qu'en float. Il faudra donc résoudre 2 problèmes:

    1- il faut faire une partie de la bibliothèque des fonctions transcendantes qui utilise les nb "Decimal()", en particulier exp, sin et cos.

    2 -avec cela, tu pourras faire des calculs en grands nombres complexes, y compris l'exponentiel du nb complexe (x+yj).

    Pour te montrer que ce n'est pas hors de portée, je viens de faire "sur les genoux" les 3 fonctions exp, sin et cos. Je n'ai fait que d'utiliser les séries convergentes habituelles. Attention: ça marche, mais je n'ai pas testé à fond, en particulier aux valeurs limites.

    Fonction exponentielle de x en utilisant le module decimal:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    for decimal import *
     
    def expdec(x, nbc=None):
        """Calcul de e à la puissance x avec nbc chiffres significatifs"""
        if type(x)!=type(Decimal):
            x = Decimal(str(x))
        if nbc==None:
            eps=Decimal("1.0e-" + str(getcontext().prec))
        else:
            eps=Decimal("1.0e-" + str(nbc))
        s1 = 1
        k = 1
        n = Decimal("0")
        while True:
            #print s1
            n += 1
            k *= x/n
            s2 = s1 + k
            if abs(s2-s1)<eps:
                break
            else:
                s1 = s2
        return s2
    Il faut définir la précision avec laquelle le calcul doit être fait avec getcontext().prec. Si on ne précise rien à l'appel de la fonction, celle-ci prend la précision ainsi définie. Si on n'a pas changé getcontext().prec, c'est par défaut 28 chiffres.

    Utilisation étonnante: calcul de e avec 100 chiffres après la virgule:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    getcontext().prec = 101
    print expdec(1)
    Ce qui affiche:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274
    Ce qui est identique à ce qui figure dans le document ici: http://www.wwdforum.com/uploads/4/DGTTN-2008-05-03.pdf

    Fonction sinus de x en utilisant le module decimal:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    for decimal import *
     
    def sindec(x, nbc=None):
        """Calcul du sinus de x avec nbc chiffres après la virgule"""
        if type(x)!=type(Decimal):
            x = Decimal(str(x))
        if nbc==None:
            eps=Decimal("1.0e-" + str(getcontext().prec))
        else:
            eps=Decimal("1.0e-" + str(nbc))
        xc = x*x
        s1 = x
        k = x
        n = Decimal("0")
        while True:
            #print s1
            n += 1
            k *= -xc/(2*n*(2*n+1))
            s2 = s1 + k
            if abs(s2-s1)<eps:
                break
            else:
                s1 = s2
        return s2
    Fonction cosinus de x en utilisant le module decimal:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    for decimal import *
     
    def cosdec(x, nbc=None):
        """Calcul du cosinus de x avec nbc chiffres après la virgule"""
        if type(x)!=type(Decimal):
            x = Decimal(str(x))
        if nbc==None:
            eps=Decimal("1.0e-" + str(getcontext().prec))
        else:
            eps=Decimal("1.0e-" + str(nbc))
        xc = x*x
        s1 = 1
        k = 1
        n = Decimal("0")
        while True:
            #print s1
            n += 1
            k *= -xc/((2*n-1)*2*n)
            s2 = s1 + k
            if abs(s2-s1)<eps:
                break
            else:
                s1 = s2
        return s2
    Avec ces 2 fonctions, on peut non seulement calculer le sinus et le cosinus d'un angle en radian, mais aussi vérifier les résultats puisque sinus carré + cosinus carré est censé être égal à 1. On peut vérifier aussi, bien sûr, les résultats en comparant les 15 premiers chiffres avec ceux du module math.

    Voilà un exemple avec l'angle x=1 radian, et 50 chiffres significatifs:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    getcontext().prec = 50
    x = 1
     
    a = sindec(x)
    print a
    print "%.15f" % math.sin(x)
     
    b = cosdec(x)
    print b
    print "%.15f" % math.cos(x)
     
    c = a*a+b*b
    print c
    Ce qui affiche:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    0.84147098480789650665250232163029899962256306079837
    0.841470984807897
     
    0.54030230586813971740093660744297660373231042061794
    0.540302305868140
     
    1.0000000000000000000000000000000000000000000000000
    Pour calculer l'exponentiel d'un nombre complexe, il faut utiliser les fonctions mathématiques (voir un bon bouquin de math!) qui utiliseront les fonctions ainsi définies (peut-être faudra-t-il en plus l'arc tg?).

    Bon, moi je vais continuer parce que ça m'intéresse, mais à mon rythme. J'espère t'avoir donné un "coup de pouce "dans la bonne direction.

    Tyrtamos

  10. #10
    Membre averti
    Inscrit en
    Mars 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 44
    Par défaut
    Bonjour, bon je tiens à te remercier pour ces résultats tres complets.... et tes explications précises. je vais appliquer ta methode et donnerais des nouvelles apres mais logiquement sa devrait aller.....

    encore merci

Discussions similaires

  1. Gérer les complexes avec <complex>
    Par Poutrator dans le forum Débuter
    Réponses: 5
    Dernier message: 01/07/2010, 15h10
  2. Réponses: 5
    Dernier message: 18/07/2008, 09h18
  3. Réponses: 2
    Dernier message: 15/07/2008, 16h11
  4. Convertir un VARCHAR en DECIMAL avec test en amont
    Par Krashtest dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 11/12/2007, 10h57
  5. acepter deux decimal avec la classe BigDecimal
    Par mehdi_swatch dans le forum Langage
    Réponses: 2
    Dernier message: 15/05/2006, 12h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo