【通过Cpython3.9源码看看python中的大小整数】

news2025/1/16 18:39:05

在这里插入图片描述

小整数

/* interpreter state */

#define _PY_NSMALLPOSINTS           257
#define _PY_NSMALLNEGINTS           5

这是CPython中定义的两个常量,它们用于控制解释器状态中的小整数对象池。在CPython中,小整数对象池是一种优化机制,用于减少对常用小整数的内存分配和销毁开销。

_PY_NSMALLPOSINTS定义了正小整数对象池的大小。在这里,其值设置为257,表示解释器将为从0到256(包含0和256)的整数预分配对象并缓存。这些整数在很多场景下会被频繁使用,所以事先创建并缓存它们可以提高性能。

_PY_NSMALLNEGINTS定义了负小整数对象池的大小。在这里,其值设置为5,表示解释器将为从-1到-5(包含-1和-5)的整数预分配对象并缓存。

在Python解释器启动时,这些小整数对象会被创建并放入对象池。当需要这些整数值时,解释器会直接从对象池中获取对应的对象,而不是动态创建新对象。这样,对于这些小整数值的操作可以更快地进行,节省了内存分配和销毁的开销。

static PyObject *
get_small_int(sdigit ival)
{
    assert(IS_SMALL_INT(ival));
    PyThreadState *tstate = _PyThreadState_GET();
    PyObject *v = (PyObject*)tstate->interp->small_ints[ival + NSMALLNEGINTS];
    Py_INCREF(v);
    return v;
}

typedef int32_t sdigit; /* signed variant of digit */

#define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)

这是get_small_int函数的实现,它用于从小整数对象池中获取一个指定值的小整数对象。小整数对象池包含了一定范围内的整数对象,主要是为了避免对这些常用的整数对象进行频繁的内存分配和销毁。

get_small_int函数接受一个sdigit类型的参数ival,表示要获取的整数值。在函数内部,首先使用assert(IS_SMALL_INT(ival))确保传入的整数值ival在小整数对象池的范围内。

接下来,函数获取当前线程状态(PyThreadState)并从其中获取解释器状态(tstate->interp)。解释器状态包含了小整数对象池,即small_ints数组

然后,根据ival计算出在small_ints数组中的索引(ival + NSMALLNEGINTS),并将对应位置的对象赋值给vNSMALLNEGINTS是一个宏定义,表示负小整数的个数。假设我们有一个整数值 ival,我们想要在 small_ints 数组中查找这个值对应的预分配的小整数对象。NSMALLNEGINTS 是预分配的负数的数量。在 CPython 中,NSMALLNEGINTS 的值通常为5,表示有5个预分配的负整数对象(-1, -2, -3, -4, -5)。

现在,我们将通过计算 ival + NSMALLNEGINTS 来找到 small_ints 数组中的索引。例如,假设 ival 为3。那么,我们可以计算索引如下:

index = ival + NSMALLNEGINTS
index = 3 + 5
index = 8

这意味着 small_ints 数组中的第8个元素(从0开始计数)是我们要查找的整数对象。在这个例子中,我们将找到预分配的小整数对象3,并将其引用计数加1,然后返回这个对象。

接下来,通过调用Py_INCREF(v)增加v的引用计数,以防止对象在其引用计数变为0时被错误地回收。

最后,返回指向小整数对象的指针v

总之,get_small_int函数的作用是从小整数对象池中获取一个指定值的小整数对象,并增加其引用计数,然后返回该对象。这样可以提高对常用小整数的操作性能。

大整数

/* Long integer representation.
   The absolute value of a number is equal to
        SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
   Negative numbers are represented with ob_size < 0;
   zero is represented by ob_size == 0.
   In a normalized number, ob_digit[abs(ob_size)-1] (the most significant
   digit) is never zero.  Also, in all cases, for all valid i,
        0 <= ob_digit[i] <= MASK.
   The allocation function takes care of allocating extra memory
   so that ob_digit[0] ... ob_digit[abs(ob_size)-1] are actually available.

   CAUTION:  Generic code manipulating subtypes of PyVarObject has to
   aware that ints abuse  ob_size's sign bit.
*/

这是CPython源码中关于长整数表示的一段注释。它解释了PyLongObject如何表示大整数的绝对值和符号。让我们逐行分析这个注释:

  1. 首先,注释指出大整数的绝对值等于:

    SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
    

    ob_digit表示长整数的每个“数字”,SHIFT是每个“数字”的位数,通常为30或15。ob_size表示长整数的符号和长度,它的绝对值表示长整数的长度,即“数字”的个数。

  2. 对于负数,ob_size小于0。对于0,ob_size等于0。

  3. 在规范化的数中,最高有效位(即最高“数字”)永远不会为零。此外,在所有情况下,对于所有有效的i,ob_digit[i]的取值范围在0到MASK之间。MASK的值通常为(1 << PyLong_SHIFT) - 1,即2**PyLong_SHIFT - 1

  4. 注释还提到分配函数负责分配额外的内存,以确保ob_digit[0]ob_digit[abs(ob_size)-1]实际上是可用的。

  5. 最后,注释中的“警告”部分提醒开发者,操纵PyVarObject子类型的通用代码需要注意整数会滥用ob_size的符号位。这是因为ob_size的符号位同时表示整数的长度和符号,而通常情况下ob_size仅用于表示长度。

额外解释

ob_digit 是一个表示大整数中每个 “数字” 的数组,它是一个整数数组,用于表示长整数对象(PyLongObject)中的整数值。每个 “数字” 都有一个固定的位数,由 PyLong_SHIFT 定义(通常为 30 或 15)。例如,假设我们有一个长整数对象,其值为 12345678901234567890。

在这个例子中,假设 PyLong_SHIFT 为 30,这意味着每个 “数字” 可以表示 2^30 = 1073741824 个不同的值。为了将这个大整数表示为 ob_digit 数组,我们需要将整数拆分为基于 2^30 的 “数字”。在这种情况下,我们可以将整数表示为:

12345678901234567890 = 4 * 2^(30*2) + 726238597 * 2^(30*1) + 1026062870 * 2^(30*0)

所以,ob_digit 数组将包含以下元素:

ob_digit[0] = 1026062870
ob_digit[1] = 726238597
ob_digit[2] = 4

在实际的 CPython 源码中,PyLongObject 的定义如下:

typedef struct {
    PyObject_VAR_HEAD
    digit ob_digit[1];
} PyLongObject;

在这里,ob_digit 是一个长度为1的数组,但实际上,它是一个可变长度数组,根据所需的 “数字” 数量动态分配。要注意的是,当一个 PyLongObject 被创建时,会根据整数值的大小动态分配适当数量的空间来存储 ob_digit 数组。

总之,ob_digit 是一个整数数组,用于表示长整数对象中的大整数值。每个数组元素都是一个 “数字”,具有固定的位数。这种表示方法使得 CPython 能够有效地存储和处理大整数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/415564.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

轨迹相似度整理

1 基于点之间的距离 1.1 欧几里得距离 优点&#xff1a;线性计算时间缺点&#xff1a;轨迹长度必须一样 1.2 DTW DTW 笔记&#xff1a; Dynamic Time Warping 动态时间规整 &#xff08;&DTW的python实现&#xff09; 【DDTW&#xff0c;WDTW】_UQI-LIUWJ的博客-CSDN博客 …

Golang流媒体实战之六:lal拉流服务源码阅读

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 《Golang流媒体实战》系列的链接 体验开源项目lal回源转推和录制lalserver的启动源码阅读Golang流媒体实战之五&#xff1a;lal推流服务源码阅读Golang流媒体…

大数据3 -Hadoop HDFS-分布式文件系统

目录 1.为什么需要分布式存储&#xff1f; 2. HDFS的基础架构 3. HDFS存储原理 4. NameNode是如何管理Block块的 5. HDFS数据的读写流程 1.为什么需要分布式存储&#xff1f; •数据量太大&#xff0c;单机存储能力有上限&#xff0c;需要靠数量来解决问题•数量的提升带…

【区块链】走进web3的世界-合约交互中的异常/边界处理

在以太坊智能合约中&#xff0c;异常处理是一个非常重要的问题&#xff0c;因为任何一个函数调用都有可能导致异常。常见的异常包括函数调用失败、无效参数、内部错误等。 在 Solidity 中&#xff0c;可以使用 require、assert 和 revert 等关键字来处理异常。这些关键字可以用…

第一章 序言:Pytorch在自然语言处理中的应用

01 序言&#xff1a;Pytorch在自然语言处理中的应用 目录01 序言&#xff1a;Pytorch在自然语言处理中的应用1. PyTorch简介2. 自然语言处理3. PyTorch在自然语言处理中的应用3.1 文本分类3.2 情感分析3.3 机器翻译4. 结论1. PyTorch简介 首先&#xff0c;我们需要介绍一下PyT…

WINDOWS消息

WINDOWS消息 Unit01消息队列 01消息队列概念 消息队列是用于存放消息的队列消息在队列中先进先出所有窗口程序都有消息队列程序&#xff08;GetMessage&#xff09;可以从队列中获消息 02消息队列分类 系统消息队列&#xff1a;由系统维护的消息队列&#xff08;这个队列非…

Qt的内存管理机制

QObject的parent设置为null 1.如果构造时直接指定了null&#xff0c;当前实例不会有父对象存在&#xff0c;Qt也不能自动析构该实例&#xff0c;除非实例超出作用域导致析构函数被调用&#xff0c;使用deletelater()函数&#xff0c;不建议使用delete 2.如果指定了parent&#…

关于电商商品数据API接口列表,你想知道的(详情页、Sku信息、商品描述、评论问答列表)

目录 一、商品数据API接口列表 二、商品详情数据API调用代码item_get 三、获取sku详细信息item_sku 四、获得淘宝商品评论item_review 五、数据说明文档 进入 一、商品数据API接口列表 二、商品详情数据API调用代码item_get <?php// 请求示例 url 默认请求参数已经URL…

数据结构-插入排序

一.概要 插入排序是一种基于比较的排序算法&#xff0c;其基本思想是将待排序的元素插入到已排序的序列中&#xff0c;形成新的有序序列。 插入排序算法的过程如下&#xff1a; 将待排序序列分为两部分&#xff1a;已排序部分和未排序部分&#xff1b; 初始时&#xff0c;已…

C++string类的详细使用方法

String类的详细使用 文章目录String类的详细使用初始化扩容空间resize与reserve扩容长度获取插入与删除函数运算符插入append插入assign字符串截取push_back尾插erase删除replase替换swap交换pop_back尾删substr截断字符串功能copy拷贝find查找rfind反向查找find_first_of匹配查…

三路快排(基于三指针单趟排序的快速排序)+快排时间复杂度再分析

目录 一.前言 二. 三路快排 &#x1f60d;算法思想: &#x1f60d;算法实现步骤: &#x1f60d;三指针单趟排序的实现:​ &#x1f60d;非递归快排完全体: &#x1f914;与C标准库里的快排进行对比测试: 三.快排时间复杂度再分析 一.前言 http://t.csdn.cn/mz8dghttp://…

SolidWorks2020安装教程

破解文件及步骤 和 安装包 hf&#xff1a;SolidWorks2020 即可 &#xff08;我的推广 共中号&#xff09; Before installation, block the outgoing Internet access by means of Windows Firewall or cord plug. Check .NET Framework 3.5 and 4.0 are installed. If .NET …

Hive安装与操作

目录 环境 数据 实验步骤与结果 &#xff08;1&#xff09;环境启动 &#xff08;2&#xff09;Hive基本操作 环境 Hadoop集群开发环境、mysql、Hive环境 数据 course.txt、sc.txt、student.txt 实验步骤与结果 &#xff08;1&#xff09;环境启动 ①执行命令&#xf…

JVM的内存结构(超详细附加大厂面试题)

内存结构 1、什么是 JVM &#xff1f; 1&#xff09;定义 Java Virtual Machine &#xff0c;Java 程序的运行环境&#xff08;Java 二进制字节码的运行环境&#xff09;。 2&#xff09;好处 一次编译&#xff0c;处处执行 自动的内存管理&#xff0c;垃圾回收机制 数组下…

结构重参数化宇宙(Re-parameterization Universe)

文章目录0. 前言1. Re-parameterization Universe1.1 RepVGG1.2. RepOptimizer2. 应用参考资料0. 前言 一方面&#xff0c;大量研究表明&#xff0c;多分支网络架构的性能普遍优于单分支架构&#xff1b;另一方面&#xff0c;相比多分支架构&#xff0c;单分支架构更有利于部署…

windows系统管理_windows server 2016 用户管理

用户账户的概述 **计算机用户账户&#xff1a;**由将用户定义到某一系统的所有信息组成的记录,账户为用户或计算机提供安 全凭证&#xff0c;包括用户名和用户登陆所需要的密码&#xff0c;以及用户使用以便用户和计算机能够登录到网络并 访问域资源的权利和权限。不同的身份拥…

自动控制原理模拟卷2

自动控制原理模拟题二 Question1 电炉温度控制系统原理如下图所示,分析系统保持电炉温度恒定的工作过程,指出系统的被控对象、被控量及各部件的作用,并画出系统方块图。 解: 电炉使用电阻丝加热,并要求保持炉温恒定,图中采用热电偶来测量电炉温并将其转换为电压信号,将…

Android 新版 Logcat 操作小技巧

新版的Android Studio中启用了新的 Logcat&#xff0c;有些小技巧这里介绍一下&#xff1a; 文章目录1. Logcat启动2. Logcat 搜索1. 搜索当前包名下的日志&#xff1a;2. 添加日志级别3. 添加标签4. 标签字段5. 排除字段6. 使用正则表达式7. 使用正则表达式排除8. 使用age截取…

初识C语言 ——“C Primer Plus”

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;小雅兰的内容是读一本好书&#xff0c;这一本书的名字就叫做《C Primer Plus》&#xff0c;那么&#xff0c;又回到了我们的初识C语言阶段啦&#xff0c;保证零基础都能看懂噢&#xff0c;下面&#xff0c;让我们进入C语言的…

app抓包实战

文章目录一、抓包原理二、常用应用场景三、过滤四、重发五、修改请求六、断点&#xff08;BreakPoint&#xff09;一、抓包原理 二、常用应用场景 解决移动端接口测试 解决接口测试过程中检查传参错误问题 mock测试&#xff08;虚拟的对象代替正常的数据、后端接口没有开发完成…