Maison  >  Article  >  développement back-end  >  Quel est le principe d'implémentation des nombres à virgule flottante dans la machine virtuelle Python ?

Quel est le principe d'implémentation des nombres à virgule flottante dans la machine virtuelle Python ?

王林
王林avant
2023-04-21 18:43:09937parcourir

    Structure de données flottantes

    La définition de la structure de données du type nombre à virgule flottante dans la machine virtuelle cpython est la suivante :

    typedef struct {
        PyObject_HEAD
        double ob_fval;
    } PyFloatObject;

    La définition de la structure de données ci-dessus est la suivante :

    Quel est le principe dimplémentation des nombres à virgule flottante dans la machine virtuelle Python ?

    • Les données ci-dessus structure Le champ le plus important d'entre eux est ob_fval, c'est là que les nombres à virgule flottante sont réellement stockés.

    • ob_refcnt est le nombre de références de l'objet.

    • ob_type est le type d'objet.

    Méthodes associées pour les nombres à virgule flottante

    Créer des objets flottants

    Semblable aux tuples et aux objets de liste dont nous avons parlé plus tôt, lorsque le type float est implémenté en interne dans cpython, une couche intermédiaire sera également créée pour l'objet float. Accélérez l'allocation de mémoire des nombres à virgule flottante. Le code spécifique pertinent est le suivant :

    #define PyFloat_MAXFREELIST    100
    static int numfree = 0;
    static PyFloatObject *free_list = NULL;

    Faire long à l'intérieur de cpython mettra en cache l'espace mémoire de 100 objets flottants, s'il dépasse 100, la mémoire sera libérée directement. Ce qu'il faut noter ici, c'est que seuls tous les objets float peuvent être mis en cache à l'aide d'un pointeur. Comment cela est-il réalisé ?

    Ceci est implémenté à l'aide du champ struct _typeobject *ob_type; dans l'objet PyFloatObject. Utilisez ce champ pour pointer vers l'espace mémoire du prochain objet float. Étant donné que les données de free_list ne sont pas utilisées, vous pouvez utiliser cette fonctionnalité pour en enregistrer. espace mémoire. Voici le processus spécifique de création d'un objet float :

    PyObject *
    PyFloat_FromDouble(double fval)
    {
        // 首先查看 free_list 当中是否有空闲的 float 对象
        PyFloatObject *op = free_list;
        if (op != NULL) {
            // 如果有 那么就将让 free_list 指向 free_list 当中的下一个 float 对象 并且将对应的个数减 1
            free_list = (PyFloatObject *) Py_TYPE(op);
            numfree--;
        } else {
          	// 否则的话就需要申请内存空间
            op = (PyFloatObject*) PyObject_MALLOC(sizeof(PyFloatObject));
            if (!op)
                return PyErr_NoMemory();
        }
        /* Inline PyObject_New */
        (void)PyObject_INIT(op, &PyFloat_Type); // PyObject_INIT 这个宏的主要作用是将对象的引用计数设置成 1
        op->ob_fval = fval;
        return (PyObject *) op;
    }

    Addition

    Ce qui suit est l'implémentation spécifique de l'ajout de nombres à virgule flottante dans cpython. L'ensemble du processus est relativement simple, il suffit d'obtenir la nouvelle valeur, d'en créer une nouvelle. PyFloatObject et ajoutez ce retour d'objet.

    static PyObject *
    float_add(PyObject *v, PyObject *w)
    {
        double a,b;
        CONVERT_TO_DOUBLE(v, a); // CONVERT_TO_DOUBLE 这个宏的主要作用就是将对象的 ob_fval 这个字段的值保存到 a 当中
        CONVERT_TO_DOUBLE(w, b); // 这个就是将 w 当中的 ob_fval 字段的值保存到 b 当中
        a = a + b;
        return PyFloat_FromDouble(a); // 创建一个新的 float 对象 并且将这个对象返回
    }

    Soustraction

    Il en va de même pour la soustraction.

    static PyObject *
    float_sub(PyObject *v, PyObject *w)
    {
        double a,b;
        CONVERT_TO_DOUBLE(v, a);
        CONVERT_TO_DOUBLE(w, b);
        a = a - b;
        return PyFloat_FromDouble(a);
    }

    Multiplication

    static PyObject *
    float_mul(PyObject *v, PyObject *w)
    {
        double a,b;
        CONVERT_TO_DOUBLE(v, a);
        CONVERT_TO_DOUBLE(w, b);
        PyFPE_START_PROTECT("multiply", return 0)
        a = a * b;
        PyFPE_END_PROTECT(a)
        return PyFloat_FromDouble(a);
    }

    Division

    static PyObject *
    float_div(PyObject *v, PyObject *w)
    {
        double a,b;
        CONVERT_TO_DOUBLE(v, a);
        CONVERT_TO_DOUBLE(w, b);
        if (b == 0.0) {
            PyErr_SetString(PyExc_ZeroDivisionError,
                            "float division by zero");
            return NULL;
        }
        a = a / b;
        return PyFloat_FromDouble(a);
    }

    Negation

    Une ligne d'instructions de sortie est ajoutée ici, c'est pour notre commodité lors des tests ultérieurs.

    static PyObject *
    float_neg(PyFloatObject *v)
    {
        printf("%.2lf 正在进行取反运算\n", v->ob_fval);
        return PyFloat_FromDouble(-v->ob_fval);
    }

    Trouvez la valeur absolue

    static PyObject *
    float_abs(PyFloatObject *v)
    {
        printf("%.2lf 正在进行取 abs 运算\n", v->ob_fval);
        return PyFloat_FromDouble(fabs(v->ob_fval));
    }

    Trouvez la valeur booléenne

    static int
    float_bool(PyFloatObject *v)
    {
        printf("%.2lf 正在进行取 bool 运算\n", v->ob_fval);
        return v->ob_fval != 0.0;
    }

    L'image ci-dessous est notre modification du programme cpython !

    Quel est le principe dimplémentation des nombres à virgule flottante dans la machine virtuelle Python ?

    Ce qui suit est le résultat lorsque nous exploitons à nouveau les nombres à virgule flottante après la modification. Ce que vous pouvez voir, c'est que les instructions que nous avons ajoutées au code ci-dessus sont affichées.

    Quel est le principe dimplémentation des nombres à virgule flottante dans la machine virtuelle Python ?

    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