cpython 仮想マシンにおける浮動小数点数型のデータ構造定義は次のとおりです。
typedef struct { PyObject_HEAD double ob_fval; } PyFloatObject;
上記のデータの構造定義図は次のとおりです。
#上記のデータ構造で最も重要なフィールドは ob_fval で、ここに浮動小数点数が格納されます。実際に保管されている。
ob_refcnt は、オブジェクトの参照カウントです。
ob_type はオブジェクトのタイプです。
cpython 内で前述したタプル オブジェクトとリスト オブジェクトと同じです。 float 型では、浮動小数点数のメモリ割り当てを高速化するために、中間層も float オブジェクトに追加されます。具体的な関連コードは次のとおりです:
#define PyFloat_MAXFREELIST 100 static int numfree = 0; static PyFloatObject *free_list = NULL;
cpython 内でさらに実行すると、100 個の float オブジェクトがキャッシュされます。メモリ空間が 100 を超える場合、メモリは直接解放されます。ここで注意する必要があるのは、すべての float オブジェクトは 1 つのポインタだけでキャッシュできることです。これはどのように実現されるのでしょうか。
これは、オブジェクト PyFloatObject の struct _typeobject *ob_type; フィールドを使用して実装されます。free_list のデータは使用されないため、このフィールドを使用して次の float オブジェクトのメモリ空間をポイントします。この機能 メモリスペースを節約します。以下は、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; }
次は、cpython での浮動小数点数の加算の具体的な実装です。プロセス全体は比較的単純です。新しい値を取得し、新しい値を作成します。PyFloatObject オブジェクトを取得し、このオブジェクトを返します。
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 对象 并且将这个对象返回 }
引き算も同様です。
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); }
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); }
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); }
出力ステートメントの行がここに追加されます。これは、後でテストする際の便宜のためです。
static PyObject * float_neg(PyFloatObject *v) { printf("%.2lf 正在进行取反运算\n", v->ob_fval); return PyFloat_FromDouble(-v->ob_fval); }
static PyObject * float_abs(PyFloatObject *v) { printf("%.2lf 正在进行取 abs 运算\n", v->ob_fval); return PyFloat_FromDouble(fabs(v->ob_fval)); }
static int float_bool(PyFloatObject *v) { printf("%.2lf 正在进行取 bool 运算\n", v->ob_fval); return v->ob_fval != 0.0; }
下の図は cpython プログラムの修正です。
#修正後に再度浮動小数点数を演算すると、上記のコードに追加した文が出力されていることがわかります。以上がPython 仮想マシンにおける浮動小数点数の実装原理は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。