在以前的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就会这样存储:

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 需要两个数组元素存放

以此类推……

通过代码来看:

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-1,2^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 的倍数,可能是某种优化算法。

见源码:

https://github.com/python/cpython/blob/d8c93aa5d29d3cab537357018d5806a57452a8fe/Include/longintrepr.h#L24

https://github.com/python/cpython/blob/d8c93aa5d29d3cab537357018d5806a57452a8fe/Objects/longobject.c#L4449

文章参考:https://segmentfault.com/a/1190000015284473

Python 3 的 int 类型详解(为什么 int 不存在溢出问题?)的更多相关文章

  1. MySQL数据类型 int(M) 表示什么意思?详解mysql int类型的长度值问题

    MySQL 数据类型中的 integer types 有点奇怪.你可能会见到诸如:int(3).int(4).int(8) 之类的 int 数据类型.刚接触 MySQL 的时候,我还以为 int(3) ...

  2. Python调用windows下DLL详解

    Python调用windows下DLL详解 - ctypes库的使用 2014年09月05日 16:05:44 阅读数:6942 在python中某些时候需要C做效率上的补充,在实际应用中,需要做部分 ...

  3. Python包模块化调用方式详解

    Python包模块化调用方式详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一般来说,编程语言中,库.包.模块是同一种概念,是代码组织方式. Python中只有一种模块对象类型 ...

  4. C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解

    前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.之前分享过一篇 C#进阶系列——WebApi接口传参不再困惑:传参详解  ...

  5. C++11 并发指南六(atomic 类型详解三 std::atomic (续))

    C++11 并发指南六( <atomic> 类型详解二 std::atomic ) 介绍了基本的原子类型 std::atomic 的用法,本节我会给大家介绍C++11 标准库中的 std: ...

  6. C++11 并发指南六( <atomic> 类型详解二 std::atomic )

    C++11 并发指南六(atomic 类型详解一 atomic_flag 介绍)  一文介绍了 C++11 中最简单的原子类型 std::atomic_flag,但是 std::atomic_flag ...

  7. Python中的高级数据结构详解

    这篇文章主要介绍了Python中的高级数据结构详解,本文讲解了Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint这些数据结构的用法,需要的朋友可以参考 ...

  8. [转]使用python来操作redis用法详解

    转自:使用python来操作redis用法详解 class CommRedisBase(): def __init__(self): REDIS_CONF = {} connection_pool = ...

  9. (转)C# WebApi 接口返回值不困惑:返回值类型详解

    原文地址:http://www.cnblogs.com/landeanfen/p/5501487.html 正文 前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi ...

随机推荐

  1. E203 bypass buffer

    如果fifo中没有数据,且有输入,则是bypass fifo,同周期内直接把输入数据转到输出数据.如果fifo中有数据,则读取fifo,成为普通的同步fifo. module sirv_gnrl_by ...

  2. jQuery的$().each()与$.each()的区别

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  3. Python必备面试题

    Python部分 1. __new__.__init__区别,如何实现单例模式,有什么优点   __new__是一个静态方法,__init__是一个实例方法 __new__返回一个创建的实例,__in ...

  4. 15、iptables详解

    --     http://www.netfilter.org/ http://www.iptables.org/     --参考路径 http://www.netfilter.org/docume ...

  5. Grafana数据迁移

    各系统和docker安装官方文档 https://grafana.com/grafana/download?platform=linux ubuntu安装相应版本的Grafana wget https ...

  6. linux (04) linux安装mysql

    https://www.cnblogs.com/pyyu/p/9467289.html mysql博客 一.mysql (分支 mariadb) 1.安装mariadb ​ -yum ​ -源码编译安 ...

  7. JDK8在接口中引入的default

    default关键字介绍 default是在java8中引入的关键字,也可称为Virtual extension methods——虚拟扩展方法.是指,在接口内部包含了一些默认的方法实现(也就是接口中 ...

  8. 维护带修改区间 K 小值

    就是在原来的主席树模板上加上一条将x上的值修改为k 待我们仔细想想之前静态的区间Kth怎么实现的... 我们仍然需要维护前缀和,而只是在以前的代码里面加上单点修改的操作,那么你要每次要修改的前缀和就有 ...

  9. E05 【餐厅】What kind of coffee or tea would you like?

    核心句型 What  kind  of  coffee or tea would you like? 你想喝什么咖啡或者茶? What  would  you like? 你喜欢什么?/你想要什么? ...

  10. django之cookies,session 、中间件及跨站请求伪造

    cookies 和session 为什么会有cookie? ​ 由于http协议是无状态的,即用户访问过后,不留痕迹(状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被 ...