python整型为空的情况_深度剖析凭什么python中整型不会溢出
前言
不溢出的整型的可行性
[longintrepr.h]
struct _longobject {
PyObject_VAR_HEAD
int *ob_digit;
};
长整型的保存形式
ob_digit[0] = 789;
ob_digit[1] = 456;
ob_digit[2] = 123;
#define PyLong_SHIFT 15
#define PyLong_BASE ((digit)1 << PyLong_SHIFT)
#define PyLong_MASK ((digit)(PyLong_BASE - 1))
长整型的运算
ob_digit[2]
ob_digit[1]
ob_digit[0]
加数a
23
934
543
加数b
+
454
632
结果z
24
389
175
[longobject.c]
static PyLongObject * x_add(PyLongObject *a, PyLongObject *b) {
int size_a = len(a), size_b = len(b);
PyLongObject *z;
int i;
int carry = 0; // 进位
// 确保a是两个加数中较大的一个
if (size_a < size_b) {
// 交换两个加数
swap(a, b);
swap(&size_a, &size_b);
}
z = _PyLong_New(size_a + 1); // 申请一个能容纳size_a+1个元素的长整型对象
for (i = 0; i < size_b; ++i) {
carry += a->ob_digit[i] + b->ob_digit[i];
z->ob_digit[i] = carry & PyLong_MASK; // 掩码
carry >>= PyLong_SHIFT; // 移除低15位, 得到进位
}
for (; i < size_a; ++i) { // 单独处理a中高位数字
carry += a->ob_digit[i];
z->ob_digit[i] = carry & PyLong_MASK;
carry >>= PyLong_SHIFT;
}
z->ob_digit[i] = carry;
return long_normalize(z); // 整理元素个数
}
乘法运算
操作
ob_digit[2]
ob_digit[1]
ob_digit[0]
乘数a
23
934
543
乘数b
*
454
632
结果z
15
126
631
176
10
866
282
522
结果z
10
881
409
153
176
// 为方便理解,会与cpython中源码部分稍有不同
static PyLongObject * x_mul(PyLongObject *a, PyLongObject *b)
{
int size_a = len(a), size_b = len(b);
PyLongObject *z = _PyLong_New(size_a + size_b);
memset(z->ob_digit, 0, len(z) * sizeof(int)); // z 的数组清 0
for (i = 0; i < size_b; ++i) {
int carry = 0; // 用一个int保存元素之间的乘法结果
int f = b->ob_digit[i]; // 当前乘数b的元素
// 创建一个临时变量,保存当前元素的计算结果,用于累加
PyLongObject *temp = _PyLong_New(size_a + size_b);
memset(temp->ob_digit, 0, len(temp) * sizeof(int)); // temp 的数组清 0
int pz = i; // 存放到临时变量的低位
for (j = 0; j < size_a; ++j) {
carry = f * a[j] + carry;
temp[pz] = carry & PyLong_MASK; // 取低15位
carry = carry >> PyLong_SHIFT; // 保留进位
pz ++;
}
if (carry){ // 处理进位
carry += temp[pz];
temp[pz] = carry & PyLong_MASK;
carry = carry >> PyLong_SHIFT;
}
if (carry){
temp[pz] += carry & PyLong_MASK;
}
temp = long_normalize(temp);
z = x_add(z, temp);
}
return z
}
总结
[longobject.c]
PyObject * PyLong_FromString(const char *str, char **pend, int base)
{
}
参考
附录
# 例子中的表格中,数组元素最多存放3位整数,因此这边设置1000
# 对应的取低位与取高位也就变成对 1000 取模和取余操作
PyLong_SHIFT = 1000
PyLong_MASK = 999
# 以15位长度的二进制
# PyLong_SHIFT = 15
# PyLong_MASK = (1 << 15) - 1
def long_normalize(num):
"""
去掉多余的空间,调整数组的到正确的长度
eg: [176, 631, 0, 0] ==> [176, 631]
:param num:
:return:
"""
end = len(num)
while end >= 1:
if num[end - 1] != 0:
break
end -= 1
num = num[:end]
return num
def x_add(a, b):
size_a = len(a)
size_b = len(b)
carry = 0
# 确保 a 是两个加数较大的,较大指的是元素的个数
if size_a < size_b:
size_a, size_b = size_b, size_a
a, b = b, a
z = [0] * (size_a + 1)
i = 0
while i < size_b:
carry += a[i] + b[i]
z[i] = carry % PyLong_SHIFT
carry //= PyLong_SHIFT
i += 1
while i < size_a:
carry += a[i]
z[i] = carry % PyLong_SHIFT
carry //= PyLong_SHIFT
i += 1
z[i] = carry
# 去掉多余的空间,数组长度调整至正确的数量
z = long_normalize(z)
return z
def x_mul(a, b):
size_a = len(a)
size_b = len(b)
z = [0] * (size_a + size_b)
for i in range(size_b):
carry = 0
f = b[i]
# 创建一个临时变量
temp = [0] * (size_a + size_b)
pz = i
for j in range(size_a):
carry += f * a[j]
temp[pz] = carry % PyLong_SHIFT
carry //= PyLong_SHIFT
pz += 1
if carry: # 处理进位
carry += temp[pz]
temp[pz] = carry % PyLong_SHIFT
carry //= PyLong_SHIFT
pz += 1
if carry:
temp[pz] += carry % PyLong_SHIFT
temp = long_normalize(temp)
z = x_add(z, temp) # 累加
return z
a = [543, 934, 23]
b = [632, 454]
print(x_add(a, b))
print(x_mul(a, b))
python整型为空的情况_深度剖析凭什么python中整型不会溢出相关推荐
- python 去掉list元素的双引号_一天快速入门 Python
Python 是由Guido Van Rossum在 90 年代早期设计,现在是最常用的编程语言之一.特别是人工智能的火热,再加之它的语法简洁且优美,实乃初学者入门AI必备的编程语言. Python基 ...
- python零基础入门五小时教学_五小时轻松入门Python
Python 是由Guido Van Rossum在 90 年代早期设计,现在是最常用的编程语言之一.特别是人工智能的火热,再加之它的语法简洁且优美,实乃初学者入门AI必备的编程语言. Python基 ...
- python中superclass是什么_深度解析并实现python中的super(转载,好文)
大神半个月的成绩,让我看的叹为观止,建议看原帖地址,会让你对Python的描述符有更强的认识. 原文链接:https://blog.csdn.net/zhangjg_blog/article/deta ...
- python任意代码都可以缩进去_我发现了个 Python 黑魔法,执行任意代码都会自动念上一段 『平安经』...
最近的"平安经"可谓是引起了不小的风波啊. 作为一个正儿八经的程序员,最害怕的就是自己的代码上线出现各种各样的 BUG. 为此,明哥今天分享一个 Python 的黑魔法,教你如何在 ...
- python counter 出现次数最少的元素_[PY3]——找出一个序列中出现次数最多的元素/collections.Counter 类的用法...
问题 怎样找出一个序列中出现次数最多的元素呢? 解决方案 collections.Counter 类就是专门为这类问题而设计的, 它甚至有一个有用的 most_common() 方法直接给了你答案 c ...
- python两数相加有进退位_仁裁者、Python之父Guido“退位”,python何去何从?
10月30日,Python之父Guido大牛宣布退休,离开Dropbox.他发推文说,"这件事感觉既苦涩又甜蜜:苦涩的是,我马上要离开Dropbox,现在已经退休:甜蜜的是,在Dropbox ...
- python能在ipad上运行吗_如何用iPad运行Python代码?
其实,不只是iPad,手机也可以. 痛点 我组织过几次线下编程工作坊,带着同学们用Python处理数据科学问题. 其中最让人头疼的,就是运行环境的安装. 实事求是地讲,参加工作坊之前,我已经做了认真准 ...
- python的开发者太负责任了_人生苦短,我用 Python
我接触 Python 并不算早,第一次使用 Python 写生产系统的程序是2004年,那时候我已经有了几年的编程经验.当然了,现在这年头说早晚都不合适,昨天我说2000年就开始使用 Vim 编程了, ...
- 在python官网如何下载手机版_如何下载各种版本Python?
1.目的 本文目的在于,对于不熟悉Python的人,教你: 1. 从哪里找到可以下载到各种版本的,包括Python 2.x和Python 3.x的最新版本的Python. 2.以及解释一下,如何选择合 ...
- go test 如何输出到控制台_深度剖析 Go 中的 Go 协程 (goroutines) -- Go 的并发
Go 协程 (goroutine) 是指在后台中运行的轻量级执行线程,go 协程是 Go 中实现并发的关键组成部分. 在上次的课程中,我们学习了 Go 的并发模型.由于 Go 协程相对于传统操作系统中 ...
最新文章
- 牛客华为机试第8题python
- intelli idea新建无scala class选项解决方案
- RocketMQ各种集群模式介绍
- Kitten编程猫里如何先后播放不同的背景音乐
- 【无码专区7】括号序列(思维)
- php,Allowed memory size of 8388608 bytes exhausted (tried to allocate 1298358 bytes)
- Go-fastdfs分布式文件系统搭建
- Web开发:Apache2.2.x+Tomcat6.x+jk2.x做集群配置
- 计算机用户要以ADSL,建设项目进度控制超星尔雅期末答案
- 微信表情包的制作以及50*50像素图片太模糊的处理方法
- GPRS远程开关 2 AIR202模块
- linux log原理,linux系统日志管理工具logrotate之原理详述
- Junit5 单元测试框架的使用
- 厦大计算机学硕考研难度,一个班半数考研 厦大录取仅两成 读研是鸡肋还是围城...
- Spring mvc 中使用 kaptcha 验证码
- pip install lap出现问题
- 感谢同济子豪兄的分享-关于RCNN论文的学习(二)
- 如何批量替换文件名称中的指定字符?
- mc服务器钓鱼系统,钓鱼 - Minecraft Wiki,最详细的官方我的世界百科
- 三:debian安装,附加开店系统
热门文章
- perl学习二:简单变量
- springmvc + ibatis 框架的搭建
- 针对Web系统常用的功能测试方法浅析
- 【学习笔记】算法导论基础知识1.1
- HTML5与HTML4区别
- 【LeetCode】【字符串】题号:*640. 求解方程
- 从零基础入门Tensorflow2.0 ----六、29keras_generator读取 kaggle 10 monkeys数据
- 从零基础入门Tensorflow2.0 ----二、4.2 wide deep 模型(子类API)
- EXCEL 选中单元格并拖动等操作。
- 遥感影像校正效果检测系统代码设计与实现