长亭百川云 - 文章详情

浮点数支持的操作是怎么实现的?

古明地觉的编程教室

71

2024-07-13

楔子

本篇文章来聊一聊浮点数支持的操作,之前说过实例对象的相关操作都定义在类型对象里面,所以我们需要查看 PyFloat_Type。

// Objects/floatobject.c  
PyTypeObject PyFloat_Type = {  
    PyVarObject_HEAD_INIT(&PyType_Type, 0)  
    "float",  
    sizeof(PyFloatObject),  
    // ......  
    // 浮点数的 __repr__ 方法  
    (reprfunc)float_repr,              /* tp_repr */  
    // 浮点数作为数值对象拥有的算术操作  
    &float_as_number,                  /* tp_as_number */  
    // 浮点数的哈希操作  
    (hashfunc)float_hash,              /* tp_hash */  
    // 浮点数支持的比较操作  
    float_richcompare,                 /* tp_richcompare */  
    // ......  
};

还是之前说的,Python 底层的函数命名以及 API 都是很有规律的,举个例子:

  • tp_repr 字段表示实例对象的字符串格式化,在 PyFloat_Type 里面它被赋值为 float_repr。

  • tp_hash 字段表示实例对象的哈希操作,在 PyFloat_Type 里面它被赋值为 float_hash。

  • tp_richcompare 字段表示实例对象的比较操作,所有的比较运算均由该字段负责实现,在 PyFloat_Type 里面它被赋值为 float_richcompare。

下面我们来通过源码看一下底层实现。

浮点数的字符串打印

由于 PyFloat_Type 没有实现 tp_str(字段的值为 0),所以打印一个浮点数会执行 tp_repr,它对应的具体实现为 float_repr 函数。

// Objects/floatobject.c  
static PyObject *  
float_repr(PyFloatObject *v)  
{     
    PyObject *result;  // 返回值  
    char *buf;  
    // 将 Python 浮点数转成 C 的浮点数,然后再转成字符串  
    buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v),  
                                'r', 0,  
                                Py_DTSF_ADD_DOT_0,  
                                NULL);  
    if (!buf)  
        return PyErr_NoMemory();  
    // 基于 C 字符串创建 Python 字符串  
    result = _PyUnicode_FromASCII(buf, strlen(buf));  
    // 释放 buf,然后返回  
    PyMem_Free(buf);  
    return result;  
}

比较简单,当然具体的转换逻辑由 PyOS_double_to_string 函数负责,内部最终会调用 C 的库函数,感兴趣可以看一下。

浮点数的哈希值

获取浮点数的哈希值会执行 tp_hash,它对应的具体实现为 float_hash。

// Objects/floatobject.c  
static Py_hash_t  
float_hash(PyFloatObject *v)  
{  
    return _Py_HashDouble((PyObject *)v, v->ob_fval);  
}

具体的哈希计算逻辑由 _Py_HashDouble 负责,通过 v->ob_fval 拿到 C 浮点数,然后传进去计算哈希值。

感兴趣可以看一下具体的哈希值计算逻辑,该函数位于 Python/pyhash.c 中。

浮点数的比较操作

浮点数之间的比较操作由 tp_richcompare 字段负责实现,该字段的值为 float_richcompare。

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2