Maison  >  Article  >  développement back-end  >  Quel est le principe d’implémentation des nombres complexes dans la machine virtuelle Python ?

Quel est le principe d’implémentation des nombres complexes dans la machine virtuelle Python ?

王林
王林avant
2023-05-13 10:40:211338parcourir

    Structure de données complexe

    En cpython, la mise en œuvre d'une structure de données complexe est la suivante :

    typedef struct {
        double real;
        double imag;
    } Py_complex;
    #define PyObject_HEAD                   PyObject ob_base;
    typedef struct {
        PyObject_HEAD
        Py_complex cval;
    } PyComplexObject;
    typedef struct _object {
        _PyObject_HEAD_EXTRA
        Py_ssize_t ob_refcnt;
        struct _typeobject *ob_type;
    } PyObject;
    # 🎜🎜#Le diagramme de structure des données ci-dessus est le suivant :

    Quel est le principe d’implémentation des nombres complexes dans la machine virtuelle Python ?

    Les données complexes doivent être relativement simples dans l'ensemble de la machine virtuelle Python, sauf en dehors de la tête de un PyObject sont les parties réelles et imaginaires.

    • ob_refcnt, représente le nombre de décomptes de références de l'objet. Ceci est très utile pour le garbage collection. Plus tard, nous analyserons en profondeur la partie garbage collection de la machine virtuelle. .

    • ob_type, indique quel est le type de données de cet objet, en python, il est parfois nécessaire de juger le type de données des données. Par exemple, ces deux mots-clés. areinstance et type. Ce champ sera utilisé.

    • real, représente la partie réelle d'un nombre complexe.

    • imag, représente la partie imaginaire d'un nombre complexe.

    Opération complexe Certains codes inutiles ont été supprimés.

    static PyObject *
    complex_add(PyObject *v, PyObject *w)
    {
        Py_complex result;
        Py_complex a, b;
        TO_COMPLEX(v, a); // TO_COMPLEX 这个宏的作用就是将一个 PyComplexObject 中的 Py_complex 对象存储到 a 当中
        TO_COMPLEX(w, b);
        result = _Py_c_sum(a, b); // 这个函数的具体实现在下方
        return PyComplex_FromCComplex(result); // 这个函数的具体实现在下方
    }
     
    // 真正实现复数加法的函数
    Py_complex
    _Py_c_sum(Py_complex a, Py_complex b)
    {
        Py_complex r;
        r.real = a.real + b.real;
        r.imag = a.imag + b.imag;
        return r;
    }
     
    PyObject *
    PyComplex_FromCComplex(Py_complex cval)
    {
        PyComplexObject *op;
     
        /* Inline PyObject_New */
        // 申请内存空间
        op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject));
        if (op == NULL)
            return PyErr_NoMemory();
        // 将这个对象的引用计数设置成 1
        (void)PyObject_INIT(op, &PyComplex_Type);
        // 将复数结构体保存下来
        op->cval = cval;
        return (PyObject *) op;
    }

    Le processus global du code ci-dessus est relativement simple :

    Extrayez d'abord la vraie partie plurielle de PyComplexObject.

    • Ajoutez les deux nombres complexes extraits.

    • Créez un objet PyComplexObject basé sur le résultat obtenu, et renvoyez cet objet.

    • Inversion de nombre complexe

      L'opération d'inversion de nombre complexe consiste à inverser la partie réelle et la partie imaginaire. Cette opération est également relativement simple. .
    • static PyObject *
      complex_neg(PyComplexObject *v)
      {
          Py_complex neg;
          neg.real = -v->cval.real;
          neg.imag = -v->cval.imag;
          return PyComplex_FromCComplex(neg);
      }
       
      PyObject *
      PyComplex_FromCComplex(Py_complex cval)
      {
          PyComplexObject *op;
       
          /* Inline PyObject_New */
          op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject));
          if (op == NULL)
              return PyErr_NoMemory();
          (void)PyObject_INIT(op, &PyComplex_Type);
          op->cval = cval;
          return (PyObject *) op;
      }
    Fonction Repr

    Nous allons maintenant introduire une méthode intéressante, qui est la fonction repr de type complexe. Cette fonction a le même effet que la fonction __repr__ de la classe. . Voyons Voyons ce qu'est la sortie des nombres complexes :

    >>> data = complex(0, 1)
    >>> data
    1j
    >>> data = complex(1, 1)
    >>> data
    (1+1j)
    >>> print(data)
    (1+1j)

    La fonction C correspondant à la repr des nombres complexes est la suivante :

    static PyObject *
    complex_repr(PyComplexObject *v)
    {
        int precision = 0;
        char format_code = 'r';
        PyObject *result = NULL;
     
        /* If these are non-NULL, they'll need to be freed. */
        char *pre = NULL;
        char *im = NULL;
     
        /* These do not need to be freed. re is either an alias
           for pre or a pointer to a constant.  lead and tail
           are pointers to constants. */
        char *re = NULL;
        char *lead = "";
        char *tail = "";
        // 对应实部等于 0 虚部大于 0 的情况
        if (v->cval.real == 0. && copysign(1.0, v->cval.real)==1.0) {
            /* Real part is +0: just output the imaginary part and do not
               include parens. */
            re = "";
            im = PyOS_double_to_string(v->cval.imag, format_code,
                                       precision, 0, NULL);
            if (!im) {
                PyErr_NoMemory();
                goto done;
            }
        } else {
            /* Format imaginary part with sign, real part without. Include
               parens in the result. */
            // 将实部浮点数变成字符串
            pre = PyOS_double_to_string(v->cval.real, format_code,
                                        precision, 0, NULL);
            if (!pre) {
                PyErr_NoMemory();
                goto done;
            }
            re = pre;
            // 将虚部浮点数变成字符串
            im = PyOS_double_to_string(v->cval.imag, format_code,
                                       precision, Py_DTSF_SIGN, NULL);
            if (!im) {
                PyErr_NoMemory();
                goto done;
            }
            // 用什么括号包围起来
            lead = "(";
            tail = ")";
        }
        result = PyUnicode_FromFormat("%s%s%sj%s", lead, re, im, tail);
      done:
        PyMem_Free(im);
        PyMem_Free(pre);
     
        return result;
    }

    On modifie maintenant la source. programme pour changer les deux parenthèses de () ci-dessus en [], le résultat de l'exécution après compilation est le suivant :

    Vous pouvez voir que les parenthèses deviennent [].

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer