Python 实现大整数乘法算法的示例代码


Posted in Python onSeptember 17, 2019

我们平时接触的长乘法,按位相乘,是一种时间复杂度为 O(n ^ 2) 的算法。今天,我们来介绍一种时间复杂度为 O (n ^ log 3) 的大整数乘法(log 表示以 2 为底的对数)。

介绍原理

karatsuba 算法要求乘数与被乘数要满足以下几个条件,第一,乘数与被乘数的位数相同;第二,乘数与被乘数的位数应为  2 次幂,即为 2 ^ 2,  2 ^ 3, 2 ^ 4, 2 ^ n 等数值。

下面我们先来看几个简单的例子,并以此来了解 karatsuba 算法的使用方法。

两位数相乘

我们设被乘数 A = 85,乘数 B = 41。下面来看我们的操作步骤:

将 A, B 一分为二,令 p = A 的前半部分 = 8,q = A 的后半部分 = 5 , r = B 的前半部分 = 4 ,s = B 的后半部分 =  1,n = 2。通过简单的数学运算:

A * B = pq * rs = (p * 10 + q) * (r * 10 + s)  = p * r * 10 ^ 2 + (p * s + q * r ) * 10 + q * s。

令 u = p * r,v =(p - q) * (s - r),w = q * s。所以 A * B =  u * 10 ^ 2 + (u + v + w) * 10 + w。

换成数值求解的过程如下:

A * B = 85 * 41 = (8 * 10 + 5) * ( 4 * 10 + 1) = 8 * 4 * 10 * 10 + (8 * 1 + 5 * 4) * 10 + 5 * 1。

其中 u = 8 * 4 = 32,v = (8 - 5) (1 - 4) = -9,w = 5 * 1 = 5。

所以,A * B = 32 * 100 + (32 - 9 + 5) * 10 + 5 = 3485。与长乘法所得结果一致。

四位数相乘

我们设被乘数 A = 8537,乘数 B = 4123。下面来看我们的操作步骤:

将 A, B 一分为二,令 p = A 的前半部分 = 85,q = A 的后半部分 = 37 , r = B 的前半部分 = 41 ,s = B 的后半部分 =  23,n = 4。

==> 其中,u = 85 * 41, v = (85 - 37) * (23 - 41), w = 37 * 23。

==> A * B = 8537 * 4123 = u * 10 ^ 4 + (u + v + w) * 10 ^ 2 + w =  3485_0000 +34_7200 + 851 = 35198051。

在我们计算 u, v,  w 的过程中又会涉及两位数的乘法,我们继续使用 Karatsuba 算法得出两位数相乘的结果。

N 位数相乘

我们令 n 为 乘数与被乘数的位数,令 p = A 的前半部分,q = A 的后半部分, r = B 的前半部分 ,s = B 的后半部分。

==> 其中, u = p * r,v = (p - q) * (s - r),w = q * s。

所以 A * B =  u * 10 ^ n + (u + v + w) * 10 ^ (n / 2) + w。

而 u, v, w 则是两个 n / 2 位的乘法运算。我们继续调用 Karatsuba 算法计算 u, v, w 的数值。接着,我们在计算 n / 2 乘法的过程中又会遇到 n / 4 位的乘法运算……以此类推,直到我们遇到两个个位数的乘法,我们就直接返回这两个个位数乘法的结果。层层返回,最终得到 N 位数的乘法结果。

时间复杂度

我们平常使用的长乘法,是 O (n ^ 2) 的时间复杂度。比如两个 N 位数相乘,我们需要将每一位按规则相乘,所以需要计算  N * N 次乘法。而使用  Karatsuba 算法每层需要计算三次乘法,两次加法,以及若干次加法,每使用一次 karatsuba 算法,乘法规模就下降一半。

所以,对于两个 n =  2 ^ K 位数乘法运算,我们需要计算 3 ^ k 次乘法运算。而 K = log n(底数为 2), 3 ^ K = 3 ^ log n = 2  ^ (log 3 * log n) = 2 ^ (log n * log 3) = n ^ log 3 (底数为 2)。

代码实现

from math import log2, ceil
 
def pad(string: str, real_len: int, max_len: int) -> str:
  pad_len: int = max_len - real_len
  return f"{'0' * pad_len}{string}"
 
 
def kara(n1: int, n2: int) -> int:
  if n1 < 10 or n2 < 10:
    return n1 * n2
  n1_str: str = str(n1)
  n2_str: str = str(n2)
  n1_len: int = len(n1_str)
  n2_len: int = len(n2_str)
  real_len: int = max(n1_len, n2_len)
  max_len: int = 2 ** ceil(log2(real_len))
  mid_len: int = max_len >> 1
  n1_pad: str = pad(n1_str, n1_len, max_len)
  n2_pad: str = pad(n2_str, n2_len, max_len)
  p: int = int(n1_pad[:mid_len])
  q: int = int(n1_pad[mid_len:])
  r: int = int(n2_pad[:mid_len])
  s: int = int(n2_pad[mid_len:])
  u: int = kara(p, r)
  v: int = kara(q-p, r-s)
  w: int = kara(q, s)
  return u * 10 ** max_len + (u+v+w) * 10 ** mid_len + w

输出结果:

==> kara(123456, 9734) == 123456 * 9734

==> kara(1234233456756, 32459734) == 1234233456756 * 32459734

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python的绘图工具matplotlib使用实例
Jul 03 Python
Python数据库的连接实现方法与注意事项
Feb 27 Python
详解字典树Trie结构及其Python代码实现
Jun 03 Python
python数据封装json格式数据
Mar 04 Python
Python操作rabbitMQ的示例代码
Mar 19 Python
pyqt 实现在Widgets中显示图片和文字的方法
Jun 13 Python
Python根据服务获取端口号的方法
Sep 25 Python
numpy.array 操作使用简单总结
Nov 08 Python
使用apiDoc实现python接口文档编写
Nov 19 Python
基于python读取.mat文件并取出信息
Dec 16 Python
PyQt5中QTableWidget如何弹出菜单的示例代码
Feb 23 Python
matplotlib绘制正余弦曲线图的实现
Feb 22 Python
Python对接 xray 和微信实现自动告警
Sep 17 #Python
Python计算两个矩形重合面积代码实例
Sep 16 #Python
详解Python3 pickle模块用法
Sep 16 #Python
python scipy卷积运算的实现方法
Sep 16 #Python
python 三元运算符使用解析
Sep 16 #Python
python 利用pywifi模块实现连接网络破解wifi密码实时监控网络
Sep 16 #Python
Python循环实现n的全排列功能
Sep 16 #Python
You might like
PHP脚本的10个技巧(6)
2006/10/09 PHP
php设计模式 Facade(外观模式)
2011/06/26 PHP
从零开始学YII2框架(一)通过Composer安装Yii2框架
2014/08/20 PHP
Win7环境下Apache连接MySQL提示连接已重置的解决办法
2017/05/09 PHP
浅谈Laravel中的三种中间件的作用
2019/10/13 PHP
静态的动态续篇之来点XML
2006/08/15 Javascript
jquery获取ASP.NET服务器端控件dropdownlist和radiobuttonlist生成客户端HTML标签后的value和text值
2010/06/28 Javascript
javascript中的if语句使用介绍
2013/11/20 Javascript
JavaScript判断一个字符串是否包含指定子字符串的方法
2015/03/18 Javascript
javascript获取select值的方法分析
2015/07/02 Javascript
AngularJS基础 ng-click 指令示例代码
2016/08/01 Javascript
微信小程序 网络请求(GET请求)详解
2016/11/16 Javascript
jquery 仿锚点跳转到页面指定位置的实例
2017/02/14 Javascript
bootstrap可编辑下拉框jquery.editable-select
2017/10/12 jQuery
微信小程序js文件改变参数并在视图上及时更新【推荐】
2018/06/11 Javascript
浅析vue-router原理
2018/10/19 Javascript
JavaScript页面加载事件实例讲解
2019/09/01 Javascript
python网络编程学习笔记(九):数据库客户端 DB-API
2014/06/09 Python
Python编程中归并排序算法的实现步骤详解
2016/05/04 Python
pandas 小数位数 精度的处理方法
2018/06/09 Python
Python实现Mysql数据统计及numpy统计函数
2019/07/15 Python
Keras使用tensorboard显示训练过程的实例
2020/02/15 Python
Python 爬取必应壁纸的实例讲解
2020/02/24 Python
keras导入weights方式
2020/06/12 Python
了解一下python内建模块collections
2020/09/07 Python
python Autopep8实现按PEP8风格自动排版Python代码
2021/03/02 Python
李维斯德国官方网上商店:Levi’s德国
2016/09/10 全球购物
请写出char *p与"零值"比较的if语句
2014/09/24 面试题
设计部经理的岗位职责
2013/11/16 职场文书
市优秀教师事迹材料
2014/02/05 职场文书
农民工讨薪标语
2014/06/26 职场文书
2014年学习全国道德模范事迹思想汇报
2014/09/15 职场文书
2015年党风建设工作总结
2015/04/29 职场文书
初中教务主任竞聘演讲稿(范文)
2019/08/20 职场文书
Python道路车道线检测的实现
2021/06/27 Python
Python作用域和名称空间的详细介绍
2022/04/13 Python