Python 3 的 int 类型详解(为什么 int 不存在溢出问题?)

枫铃3年前 (2021-09-30)Python297

在以前的Python2中,整型分为int和long,也就是整型和长整型, 长整型不存在溢出问题, 即可以存放任意大小的数值,理论支持无限大数字。

因此在Python3 中,统一使用长整型,用int表示,在Python3中不存在long,只有int。

这个长整形int结构其实也很简单, 在 longintepr.h 中定义:

struct _longobject {
    PyObject_VAR_HEAD
    digit ob_digit[1];
};

ob_digit它是一个数组指针。digit 可认为是 int 的别名.

即长整型在Python内部是用一个int数组digit ob_digit[n]保存值的. 待存储的数值的低位信息放于低位下标, 高位信息放于高下标.比如要保存 112233445566778899 很长,但我们的int只能保存6位(假设):
那么python就会这样存储:

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333 
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
ob_digit[0] = 778899;
ob_digit[1] = 445566;
ob_digit[2] = 112233;

低位存于低索引下,高位位于高索引下。而正负符号信息由ob_size保存, 像上面的例子中对象元素个数是3, 那么ob_size = 3而如果表示数是负数的, 那么 ob_size = -3

python中整型结构中的数组,每个元素最大存储 15 位的二进制数(不同位数操作系统有差异32位系统存15位,64位系统是30位)。

如64位系统最大存储30位的二进制数,即存储的最大十进制数是 2^30-1 = 1073741823,也就是说上面例子中数组一个元素存储的最大值是1073741823。

那么存储数字 10737418231 其实是:

ob_digit[0] = 1;
ob_digit[1] = 1073741823;

需要注意的是,实际存储是以二进制形式存储,而非我们所写的十进制。

  • 十进制:1073741823 = 二进制:11111…11111(30位) 存储在高索引 1

  • 十进制:1 = 二进制:00000…000001(30位) 存储在低索引 0

1 ~ 2^30-1 需要一个数组元素存放
2^30 ~ 2^60-1 需要两个数组元素存放

以此类推……

通过代码来看:

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333 
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import sys

print("2^30 = {}\n2^60 = {}".format(1024*1024*1024, 1024*1024*1024*1024*1024*1024))

print("0, 1, 2^30-1, 2^30, 2^60-1 的字节大小: ",sys.getsizeof(0), sys.getsizeof(1), sys.getsizeof(1073741823), sys.getsizeof(1073741824), sys.getsizeof(1152921504606846975))

结果如下:

2^30 = 1073741824
2^60 = 1152921504606846976
数字 0, 1, 2^30-1, 2^30, 2^60-12^60 的字节大小:  24 28 28 32 32 36

由于Python中的int有一个基础内存占用(也就是长整形结构中PyObject_VAR_HEAD占用内存的大小,24字节),因此数字1 ~ 2^30-1 内存大小是28字节,2^30 ~ 2^60-1 内存大小是32字节,这里需要注意的是 0 占用的内存大小是24字节而非28字节!

一个数组元素的所用内存大小是4字节即32位,但其实存储数字的有效位是30位(64位系统中),少的两位去哪了???

实际存储只用了30位的原因是:指数运算中要求位移量得是 5 的倍数,可能是某种优化算法。

相关文章

利用python同步windows和linux文件

写python脚本的初衷,每次在windows编辑完文件后,想同步到linux上去,只能够登录服务器,...

爬虫基本原理

爬虫基本原理 一、爬虫是什么? 百度百科和维基百科对网络爬虫的定义:简单来说爬虫就是抓取目标网站内容的工具,一般是根据定义的行...

Django 函数和方法的区别

函数和方法的区别 1、函数要手动传self,方法不用传 2、如果是一个函数,用类名去调用,如果是一个方法...

Django 知识补漏单例模式

单例模式:(说白了就是)创建一个类的实例。在 Python 中,我们可以用多种方法来实现单例模式&#x...

Django基础知识MTV

Django简介 Django是使用Python编写的一个开源Web框架。可以用它来快速搭建一个高性能的网站。 Django也是一个MVC框架。但是在Dj...

Python mysql 索引原理与慢查询优化

一 介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。