Python:Python底层原理:Python的整数是如何实现的

news2024/10/7 16:18:57

Python整数在底层存储方式

  • 1. Python整数在底层对应的结构体 PyLongObject
  • 2.整数是怎么存储的
    • 2.1 整数0存储
    • 2.2 整数1
    • 2.3 整数-1
    • 2.4. 2**30 -1
    • 2.5 . 2**30
    • 2.6 . ob_digit[a, b, c] 对应整数计算
  • 计算整数所占内存大小
  • 总结

Python的底层是C/C++ ,但是 C/C++ 能表示的整数范围是有限的,那么Python 是如何做到:整数不溢出的了?
下面我们从以下几个方面来分析下。

  1. Python整数在底层对应的结构体 PyLongObject定义
  2. 整数是怎么存储的
  3. 整数占的内存大小是怎么计算的
  4. 两个整数是怎么比较大小
  5. 整数的加减法运算

1. Python整数在底层对应的结构体 PyLongObject

下面我们来看一下 python3.11 版本源码,它的源码是 C++语言写的

// Include/cpython/longIntrepr.h
struct _longobject {
	PyObject _VAR_HEAD
	digit ob_digit[1];
}
// Include/pytypedefs.h
typedef struct _longobject PyLongObject

// 那么将两者结合起来
typedef struct {
	PyObject _VAR_HEAD
	digit ob_digit[1];
}PyLongObject;

// 如果把这个 PyLongObject 更细致的展开一下
typedef struct
{
	// 引用计数
	Py_ssize_t  ob_refcnt;
	// 类型
	struct _typeobject *ob_type;
	// 维护的元素个数
	Py_ssize_t ob_size;
	// digit 类型的数组
	digit ob_digit[1];
}PyLongObjcet

根据上述C++存储代码,我们可以得到如下信息:

  1. ob_size 指的是 数组 ob_digit 的长度,而 ob_digit 只能用来维护具体的值,而数组长度的不同,那么对应的整数占用内存也就不同。

💚💚💚
我们再来看下: ob_digit 数组的定义

// ob_digit 定义
longintrepr.h

# if PYLONG_BITS_IN_DIGIT =30 
typedef unint32_t digit;
#elif PYLONG_BITS_IN_DIGIT =15
typedef unsigned short digit;
#endif

  • 由于现在基本都是64位机器,所以只考虑64 位,显然 PYLONG_BITS_IN_DIGIT 会等于30 。 因此 digit 等价于 unint32_t ,也就是 unsigned int ,所以它是一个 无符号32位整型。
  • 因此 ob_digit 是一个无符号 32位 整型数组,长度为1 当然这个数据具体多长则取决于你要存储的整数有多大
  • 数组的长度具体是多少,取决于你的实际整数,显然整数越大,这个数组就越长,占用的空间也就越大。

2.整数是怎么存储的

下面,我们就以 Python整数的底层存储为例,来详细解释下Python底层存储的原则。

2.1 整数0存储

当表示的整数为0时,ob_digit 数组为空,不存储任何值,而 ob_size为0, 表示这个整数的值为0, 这是一种特殊情况。
在这里插入图片描述

2.2 整数1

当存储的值为1时,此时 ob_digit 数组就是 [1] ,显然 ob_size 的值也是 1, 因为 它维护的就是 ob_digit 数组的长度。
在这里插入图片描述

2.3 整数-1

  1. 我们可以看到 ob_digit 数组没有变化,但是 ob_size长度变为 -1, 整数的正负号就是通过这里的 ob_size来决定的
  2. ob_digit 存储的其实是绝对值,无论整数 n 是多少 -n和n 对应的 digit 是完全一致的,但是 ob_size 则刚好相反,所以ob_size 除了表示数组的长度之外,还可以表示对应整数的正负。
  3. 整数越大,底层的数组就越长,更准确的说是绝对值越大,底层数组就越长。
  4. 所以,Python 在比较两个整数的大小时,会先比较 ob_size ,如果 ob_size 不一样则可以直接比较出大小,显然 ob_size越大,对应的整数越大,不管 ob_size 是正是负,都符合这个结论。
    在这里插入图片描述

2.4. 2**30 -1

如果想表示:2**30-1 , 我们直接按照前面三个小节,就可以表示这个整数值,但是为什么需要将这个整数单独拿出来说了 ?
💚💚💚
答案就是:虽然 digit 是 4字节32位,但是解释器 只用了 30位

  1. 如果32个位全部用来存储绝对值,那么相加产生进位的时候,可能会溢出 (如: 2**32-1 此时 32个位全部占满了,即便它只加1,也会溢出),为了解决这个问题:

1:可以先强制转换成 64位整数再进行运算,但是这会以影响效率。
2:但是如果只用30位的话,那么加法就不会溢出。
3:如果数值大到 30个位存不下的话,那么就会多使用一个 digit
在这里插入图片描述

2.5 . 2**30

显然 30个位能表达的最大整数是:230-1 ,它是digit 能存的最大值,而现在 是 230 , 所以数组就要有两个 digit
将两个 digit 的值相加 就可以表示 2**30-1 了。
在这里插入图片描述

2.6 . ob_digit[a, b, c] 对应整数计算

在这里插入图片描述

计算整数所占内存大小

总结

  • 因为底层使用数组存储的,而数组的长度又没限制,所以,理论上就不会溢出。

所以,要想支持任意大小的整数运算,首先要找到适合存放整数的方式,本篇介绍了用 int 数组来存放,当然也可以用字符串来存储,找到合适的数据结构后,要重新定义所有运算操作。

💚💚💚 下面这个思想可以好好想想 。
一个 8 位的无符号整数类型,我们知道它能表示的最大数字是 255,但这时候如果我想表示 256,要怎么办?
可能有人会想,那用两个数来存储不就好了。一个存储 255,一个存储 1,将这两个数放在数组里面。这个答案的话,虽然有些接近,但其实还有偏差:那就是我们并不能简单地按照大小拆分,比如 256 拆分成 255 和 1,要是 265 就拆分成 255 和 10,不能这样拆分。
正确的做法是通过二进制的方式,也就是用新的整数来模拟更高的位。
参考 https://www.jb51.net/article/266697.htm

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

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

相关文章

Linux挂载新磁盘到根目录

添加磁盘到需要挂载的机器上 lsblk查看硬盘挂载情况,sdb,sdc为我新挂载的磁盘 fdisk -l查看挂载之前的分区情况 为新硬盘创建分区 fdisk /dev/sdb 终端会提示: Command (m for help):输入:n 依次输入p…

【HTTPS】

HTTP明文传输问题 窃听风险,比如通信链路上可以获取通信内容,用户号容易没。篡改风险,比如强制植入垃圾广告,视觉污染,用户眼容易瞎。冒充风险,比如冒充淘宝网站,用户钱容易没。 TLS协议解决H…

【雅可比左乘右乘】

常见雅可比左乘(以自变量R为例子,围绕旋转点p的旋转点的左扰动雅可比): 旋转点的右扰动雅可比(右乘): 左雅可比和右雅可比之间的区别在于它们各自描述了不同的变换方向。左雅可比将输入空…

硬件-6-基站和移动通信系统的演进

1G、2G、3G、4G、5G 移动通信技术发展简史 1 移动通信系统简介 移动通信系统从第一代移动通信系统(1G)开始逐渐发展,目前已经发展到第四代移动通信系统(4G),第五代移动通信系统(5G)也已经开始标准化,预计2020年商用,6G预计2030年…

Linux网络架构: XDP, iptables/netfilter和iproute2/tc/ip/Qdiscs

本文目录 1、架构框图2、网络架构分成三大块3、网络架构-----对应的配置工具-----对应的原理与概念 说到Linux的网络架构,就离不开谈。。。这些东西。这几个概念很容易混淆起来,但如果仔细去看,就会发现这个Linux的网络架构的设计其实是非常简…

10:00面试,10:04就出来了 ,问的实在是太...

从外包出来,没想到竟然死在了另一家厂子 自从加入这家公司,每天都在加班,钱倒是给的不少,所以我也就忍了。没想到12月一纸通知,所有人都不许加班,薪资直降30%,顿时有吃不起饭的赶脚。 好在有个…

建筑专业可以转行学云计算吗?

当然可行。 在过去的几年中,我们已经帮助很多建筑土木工程专业的同学转行学习云计算技术,尤其是在建筑信息化编程方向。近年来,云计算行业持续发展,涉及到众多领域,如云数据中心、云安全、云存储、云计算机服务等。云…

管好【SD-WEBUI】中大量的模型:名称+预览图+备注

文章目录 (零)前言(一)模型(1.1)模型名称(文件名)(1.2)模型缩略图(1.3)模型备注文字(1.4)模型详细信息 &#…

国民技术N32G430开发笔记(18)- I2C1 从机收发数据

I2C1 从机收发数据 1、将PB6 PB7设置为i2c从机,跟android板卡通讯。 2、Android发送 写命令: 0x05 0x02 0x00 0x00 checksum n32将收到的命令打印出来 读版本命令: 0x01 0x02 0x00 0x00 checksum n32将app_version返回电视端 3、i2c从机配置…

MTK6765安卓智能模组5G核心板联发科MTK方案主板开发板

联发科MTK6765这是一款12纳米八核A53处理器,最高运行速度可达2.3GHz。它使用Android 9.0操作系统,配备2G16G内存,也支持其他选项1G/3G/4G8G/32G/64G。 此外,它支持全球主流频段,包括默认的国内频段以及2G GSM、2G/3G E…

【Android取证篇】ADB端口驱动更新详细步骤

【Android取证篇】ADB端口驱动更新详细步骤 更新ADB端口驱动,解决无法连接设备问题—【蘇小沐】 1、【记录VID】路径:设备管理器->便携设备->属性->(记录)VID 查看设备的VID 2、添加设备ID(VID&#xff09…

Sass 总结

文章目录 Sass 总结概述编译.scss 和 .sass变量数据类型属性值变量属性名变量 嵌套规则基本嵌套& 父选择器标识符嵌套属性 import 导入导入Sass文件私有化导入原生CSS文件 mixin 混合器无参数带参数命名参数关键字参数可变参数content 混入内容 extend 继承media 媒体查询控…

hbase查询报错unable to find region for

某天由于集群资源不足。hbase大面积 region server 负载爆炸卡死,隔天发现部分查询报错 集群中一张表某些查询找不到region 尝试了重启集群和滚动重启集群,考虑滚动重启的过程会把regionserver上的region迁出和迁入。试试能不能修复,果断的…

自定义项目Jar上传到maven中央仓库(一步到位)

中央仓库 Open Source Software Repository Hosting 简称 OSSRH 实现目标:将自定义项目上传至maven中央仓库,其他人只需引入maven坐标即可直接使用 上传步骤:亲测有效 注册账号(去它平台)提交工单(叫它做事…

USB HS-PHY眼图调试

1 USB2 PHY AFE 1.1 USB 2.0 FS PHY github ultraembedded / core_usb_fs_phy NOP USB transceiver for all USB transceiver which are either built-in into USB IP or which are mostly autonomous. 1.2 电阻参数 USB host端:D和D-各接一个15kΩ的下拉电阻&#…

数据结构学习记录——堆的建立(最大堆的建立、思路图解、代码实现、代码解释)

目录 最大堆的建立 方法1 方法2 思路图解 代码实现 代码解释 PercDown BuildHeap 最大堆的建立 建立最大堆:将已经存在的N个元素按最大堆的要求存放在一个一维数组中。 方法1 通过插入操作,将N个元素一个一个地插入到一个初始为空的堆中去。…

CSA发布|《洞察2022 云上数据安全与重要事项 》

云安全联盟大中华区就云上数据安全和重要事项的洞察和建议等相关问题展开调查并发布《洞察2022 云上数据安全与重要事项 》(以下简称《报告》)。报告的主要内容是关于云上数据安全和重要事项的洞察和建议。它包括了对云安全现状的分析、云安全风险的评估…

git的学习

文章目录 一、Git 的简介二、Git 工作流程三、Git 工作区、暂存区和版本库总结 一、Git 的简介 Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软…

【c语言】字符串比较 | API仿真

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ …

RabbitMQ可靠性消息发送(java实现)

本博客属于 《RabbitMQ基础组件封装—整体结构》的子博客 一、整体架构 step1&#xff1a;消息落库&#xff0c;业务数据存库的同时&#xff0c;也要将消息记录存入数据库&#xff0c;二者要保证原子性&#xff1b; step2&#xff1a;Producer发送消息到MQ Broker&#xff1b…