在以前的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. 【React】Redux入门 & store体验

    组件间传值联动是令人头疼的问题,尤其是一个组件影响多个其他组件状态变化的时候,常常需要一级一级与父组件传值,与父组件的兄弟组件传值等等, 如何化繁为简地处理‘牵一发动全身’的清理就是将所有组件的sta ...

  2. jquery源码问题

    最近公司升级jquery版本后,原来项目中复选框的attr的使用失效,在查看了jquery的内容的时候发现版本更新,复选框的attr的使用替换成了prop,所以使用的时候出现了问题,但是涉及到的文件太 ...

  3. Vue监控器watch的全面解析

    前言 前面讲到了计算属性computed,这次讲的是监控器watch,主要任务就是监控变量的变化 正文 watch是一个对象,键是需要观察的表达式,值是对应回调函数.值也可以是方法名,或者包含选项的对 ...

  4. django urls 配置小记

    django urls 配置小记 首先应了解 django2.0在url的配置上较之以前的版本有点区别,在之前的版本是通过django.conf.urls.url函数来实现路径配置的 urlpatte ...

  5. python实验脚本

    day1 1.  任性猜数字 需求 : 猜数字, 猜3次.如果对了 就直接退出. 如果3次都错了 ,就询问 要不要继续. 实现点: 使用 whie 循环. count 进行计数.如果count > ...

  6. style="position: relative;left:-5px; top: -5px;"

    <span class="input-sm" style="position: relative;left:-5px; top: -5px;">&l ...

  7. LG4035/BZOJ1013 「JSOI2008」球形空间产生器 高斯消元

    问题描述 LG4035 BZOJ1013 题解 设答案为\((p_1,p_2,p_3,...,p_n)\) 因为是一个球体,令其半径为\(r\),则有 \[\sum_{i=1}^{n}{(a_i-p_ ...

  8. Spring Cloud版本 version命名说明 (Edgware)

    Spring Cloud版本 version命名说明 (Edgware)   版权声明:guofangsky 版权所有,转载不究. https://blog.csdn.net/guofangsky/a ...

  9. 【Excel】截取字符 LEFT(A1,2) RIGHT(A1,2) MID(SHEET1!E2,1,9)

    LEFT(A1,2)从左边取两个字符 RIGHT(A1,2)从右边取两个字符 MID(SHEET1!E2,1,9)从sheet1表E2单元格中第一位起后9位 可以嵌套

  10. 5.Vue的组件

    1.什么是组件 组件是可复用的Vue实例,也就是一组可以复用的模版,类似JSTL的自定义标签. 你可能会有页头.侧边栏.内容区等组件,每个组件又包含了其它的像导航链接.博文之类的组件. 2.第一个Vu ...