当前位置: 首页 > 后端技术 > Python

深入理解 PYTHON 虚拟机:浮点数(FLOAT)的实现原理及源码剖析

时间:2023-03-26 12:48:25 Python

深入理解PYTHON虚拟机:??浮点数(FLOAT)类型的实现原理和源码分析类型的实现原理和他相关的一些源码。cpython虚拟机中浮点型数据结构的FLOAT数据结构定义如下:typedefstruct{PyObject_HEADdoubleob_fval;}PyFloatObject;上面的数据结构定义图如下:上面的数据结构中最重要的字段是ob_fval,这里才是真正存放浮点数的地方。ob_refcnt是对象的引用计数。ob_type是对象的类型。与浮点数相关的方法创建浮点对象与我们上面讨论的元组和列表对象相同。在cpython内部实现float类型的时候,还为float对象做了一个中间层,用来加速浮点数的内存分配。具体相关代码如下:#definePyFloat_MAXFREELIST100staticintnumfree=0;静态PyFloatObject*free_list=NULL;如果你在cpython中做100个以上的float对象,内存空间就会被缓存。如果超过100,则直接释放内存。这里需要注意的一点是如何只用一个指针来缓存所有的float对象。这是通过使用struct_typeobject*ob_type实现的;对象PyFloatObject中的字段。使用这个字段指向下一个float对象的内存空间,因为free_list中的数据没有被使用,所以可以利用这个特性来节省一些内存空间。下面是创建float对象的具体过程:PyObject*PyFloat_FromDouble(doublefval){//首先检查free_list中是否有空闲的float对象PyFloatObject*op=free_list;if(op!=NULL){//如果是,则让free_list指向free_list中的下一个float对象,并将相应的数字减1free_list=(PyFloatObject*)Py_TYPE(op);numfree--;}else{//否则需要申请内存空间op=(PyFloatObject*)PyObject_MALLOC(sizeof(PyFloatObject));如果(!op)返回PyErr_NoMemory();}/*内联PyObject_New*/(void)PyObject_INIT(op,&PyFloat_Type);计数设置为1op->ob_fval=fval;return(PyObject*)op;}addition下面是cpython中浮点数加法的具体实现。整个过程比较简单,获取一个新的值,创建一个新的PyFloatObject对象。并返回这个对象。staticPyObject*float_add(PyObject*v,PyObject*w){doublea,b;CONVERT_TO_DOUBLE(v,a);//宏CONVERT_TO_DOUBLE的主要作用是将对象的ob_fval字段的值保存到一个CONVERT_TO_DOUBLE(w,b);//这是将w中ob_fval字段的值保存到b中a=a+b;返回PyFloat_FromDouble(a);//创建一个新的float对象并返回这个对象}减法和减法是一样的。staticPyObject*float_sub(PyObject*v,PyObject*w){doublea,b;CONVERT_TO_DOUBLE(v,a);CONVERT_TO_DOUBLE(w,b);a=a-b;返回PyFloat_FromDouble(a);}乘法staticPyObject*float_mul(PyObject*v,PyObject*w){doublea,b;CONVERT_TO_DOUBLE(v,a);CONVERT_TO_DOUBLE(w,b);PyFPE_START_PROTECT("相乘",返回0)a=a*b;PyFPE_END_PROTECT(a)returnPyFloat_FromDouble(a);}除静态PyObject*float_div(PyObject*v,PyObject*w){doublea,b;CONVERT_TO_DOUBLE(v,a);CONVERT_TO_DOUBLE(w,b);if(b==0.0){PyErr_SetString(PyExc_ZeroDivisionError,“浮点除以零”);返回空值;}a=a/b;返回PyFloat_FromDouble(a);staticPyObject*float_neg(PyFloatObject*v){printf("%.2lf取反\n",v->ob_fval);returnPyFloat_FromDouble(-v->ob_fval);}求绝对值staticPyObject*float_abs(PyFloatObject*v){printf("%.2lfistakingabsoperation\n",v->ob_fval);returnPyFloat_FromDouble(fabs(v->ob_fval));}查找bool值staticintfloat_bool(PyFloatObject*v){printf("%.2lfistakeingbooloperation\n",v->ob_fval);returnv->ob_fval!=0.0;}下图是我们对cpython程序的修改!下面是修改后再次对浮点数进行运算时的输出。可以看到我们在上面代码中添加的语句被输出了。综上所述,本文主要介绍了一些float类型在CPython内部是如何实现的及其相关的加减乘除方法是如何实现的,以及一些and关键字相关的函数实现。本文主要讨论float数据类型本身,不涉及其他。其实还有很大一部分是关于类型的,就是cpython的内部对象系统是怎么实现的。这一点在后面深入讨论对象系统时会进一步分析,回过头来看float类型会有更深的理解。本文是深入理解python虚拟机系列文章之一。文章地址为:https://github.com/Chang-LeHung/dive-into-cpython更多精彩内容合集可访问:https://github.com/Chang-LeHung/CSCore关注公众号:废柴研究僧,多学点计算机(Java,Python,计算机系统基础,算法和数据结构)。