前言

不溢出的整型的可行性

[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中整型不会溢出相关推荐

  1. python 去掉list元素的双引号_一天快速入门 Python

    Python 是由Guido Van Rossum在 90 年代早期设计,现在是最常用的编程语言之一.特别是人工智能的火热,再加之它的语法简洁且优美,实乃初学者入门AI必备的编程语言. Python基 ...

  2. python零基础入门五小时教学_五小时轻松入门Python

    Python 是由Guido Van Rossum在 90 年代早期设计,现在是最常用的编程语言之一.特别是人工智能的火热,再加之它的语法简洁且优美,实乃初学者入门AI必备的编程语言. Python基 ...

  3. python中superclass是什么_深度解析并实现python中的super(转载,好文)

    大神半个月的成绩,让我看的叹为观止,建议看原帖地址,会让你对Python的描述符有更强的认识. 原文链接:https://blog.csdn.net/zhangjg_blog/article/deta ...

  4. python任意代码都可以缩进去_我发现了个 Python 黑魔法,执行任意代码都会自动念上一段 『平安经』...

    最近的"平安经"可谓是引起了不小的风波啊. 作为一个正儿八经的程序员,最害怕的就是自己的代码上线出现各种各样的 BUG. 为此,明哥今天分享一个 Python 的黑魔法,教你如何在 ...

  5. python counter 出现次数最少的元素_[PY3]——找出一个序列中出现次数最多的元素/collections.Counter 类的用法...

    问题 怎样找出一个序列中出现次数最多的元素呢? 解决方案 collections.Counter 类就是专门为这类问题而设计的, 它甚至有一个有用的 most_common() 方法直接给了你答案 c ...

  6. python两数相加有进退位_仁裁者、Python之父Guido“退位”,python何去何从?

    10月30日,Python之父Guido大牛宣布退休,离开Dropbox.他发推文说,"这件事感觉既苦涩又甜蜜:苦涩的是,我马上要离开Dropbox,现在已经退休:甜蜜的是,在Dropbox ...

  7. python能在ipad上运行吗_如何用iPad运行Python代码?

    其实,不只是iPad,手机也可以. 痛点 我组织过几次线下编程工作坊,带着同学们用Python处理数据科学问题. 其中最让人头疼的,就是运行环境的安装. 实事求是地讲,参加工作坊之前,我已经做了认真准 ...

  8. python的开发者太负责任了_人生苦短,我用 Python

    我接触 Python 并不算早,第一次使用 Python 写生产系统的程序是2004年,那时候我已经有了几年的编程经验.当然了,现在这年头说早晚都不合适,昨天我说2000年就开始使用 Vim 编程了, ...

  9. 在python官网如何下载手机版_如何下载各种版本Python?

    1.目的 本文目的在于,对于不熟悉Python的人,教你: 1. 从哪里找到可以下载到各种版本的,包括Python 2.x和Python 3.x的最新版本的Python. 2.以及解释一下,如何选择合 ...

  10. go test 如何输出到控制台_深度剖析 Go 中的 Go 协程 (goroutines) -- Go 的并发

    Go 协程 (goroutine) 是指在后台中运行的轻量级执行线程,go 协程是 Go 中实现并发的关键组成部分. 在上次的课程中,我们学习了 Go 的并发模型.由于 Go 协程相对于传统操作系统中 ...

最新文章

  1. 牛客华为机试第8题python
  2. intelli idea新建无scala class选项解决方案
  3. RocketMQ各种集群模式介绍
  4. Kitten编程猫里如何先后播放不同的背景音乐
  5. 【无码专区7】括号序列(思维)
  6. php,Allowed memory size of 8388608 bytes exhausted (tried to allocate 1298358 bytes)
  7. Go-fastdfs分布式文件系统搭建
  8. Web开发:Apache2.2.x+Tomcat6.x+jk2.x做集群配置
  9. 计算机用户要以ADSL,建设项目进度控制超星尔雅期末答案
  10. 微信表情包的制作以及50*50像素图片太模糊的处理方法
  11. GPRS远程开关 2 AIR202模块
  12. linux log原理,linux系统日志管理工具logrotate之原理详述
  13. Junit5 单元测试框架的使用
  14. 厦大计算机学硕考研难度,一个班半数考研 厦大录取仅两成 读研是鸡肋还是围城...
  15. Spring mvc 中使用 kaptcha 验证码
  16. pip install lap出现问题
  17. 感谢同济子豪兄的分享-关于RCNN论文的学习(二)
  18. 如何批量替换文件名称中的指定字符?
  19. mc服务器钓鱼系统,钓鱼 - Minecraft Wiki,最详细的官方我的世界百科
  20. 三:debian安装,附加开店系统

热门文章

  1. perl学习二:简单变量
  2. springmvc + ibatis 框架的搭建
  3. 针对Web系统常用的功能测试方法浅析
  4. 【学习笔记】算法导论基础知识1.1
  5. HTML5与HTML4区别
  6. 【LeetCode】【字符串】题号:*640. 求解方程
  7. 从零基础入门Tensorflow2.0 ----六、29keras_generator读取 kaggle 10 monkeys数据
  8. 从零基础入门Tensorflow2.0 ----二、4.2 wide deep 模型(子类API)
  9. EXCEL 选中单元格并拖动等操作。
  10. 遥感影像校正效果检测系统代码设计与实现