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读写ini文件示例(python读写文件)
Mar 25 Python
python装饰器与递归算法详解
Feb 18 Python
Python 类与元类的深度挖掘 II【经验】
May 06 Python
Python实现XML文件解析的示例代码
Feb 05 Python
对python中的for循环和range内置函数详解
Apr 17 Python
python进行文件对比的方法
Dec 24 Python
python random从集合中随机选择元素的方法
Jan 23 Python
详解用python自制微信机器人,定时发送天气预报
Mar 25 Python
详解pandas删除缺失数据(pd.dropna()方法)
Jun 25 Python
python gdal安装与简单使用
Aug 01 Python
python判断变量是否为列表的方法
Sep 17 Python
python自动化操作之动态验证码、滑动验证码的降噪和识别
Aug 30 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
第十二节--类的自动加载
2006/11/16 PHP
PHP动态变静态原理
2006/11/25 PHP
用PHP的超级变量$_POST获取HTML表单(HTML Form) 数据
2011/05/07 PHP
thinkphp视图模型查询提示ERR: 1146:Table 'db.pr_order_view' doesn't exist的解决方法
2014/10/30 PHP
php微信开发之带参数二维码的使用
2016/08/03 PHP
ajax+php实现无刷新验证手机号的实例
2017/12/22 PHP
Laravel 微信小程序后端搭建步骤详解
2019/11/26 PHP
JavaScript 节点操作 以及DOMDocument属性和方法
2007/12/06 Javascript
JS 两日期相减,获得天数的小例子(兼容IE,FF)
2013/07/01 Javascript
IE6兼容透明背景图片及解决方案
2015/08/19 Javascript
jquery实现一个简单的表单验证实例
2016/03/30 Javascript
jQuery height()、innerHeight()、outerHeight()函数的区别详解
2016/05/23 Javascript
Angular4实现动态添加删除表单输入框功能
2017/08/11 Javascript
Web技术实现移动监测的介绍
2017/09/18 Javascript
js实现随机点名系统(实例讲解)
2017/10/18 Javascript
vue小白入门教程
2018/04/02 Javascript
小程序清理本地缓存的方法
2018/08/17 Javascript
vue.js中proxyTable 转发请求的实现方法
2018/09/20 Javascript
详解可以用在VS Code中的正则表达式小技巧
2019/05/14 Javascript
Vue+elementui 实现复杂表头和动态增加列的二维表格功能
2019/09/23 Javascript
vue滚动插件better-scroll使用详解
2019/10/18 Javascript
vue+element 实现商城主题开发的示例代码
2020/03/26 Javascript
[02:46]完美世界DOTA2联赛PWL DAY4集锦
2020/11/03 DOTA
利用Python爬取可用的代理IP
2016/08/18 Python
python学习之matplotlib绘制散点图实例
2017/12/09 Python
django中的HTML控件及参数传递方法
2018/03/20 Python
Python操作MySQL数据库的方法
2018/06/20 Python
python求最大连续子数组的和
2018/07/07 Python
详解python中的生成器、迭代器、闭包、装饰器
2019/08/22 Python
Python sorted排序方法如何实现
2020/03/31 Python
PyCharm配置anaconda环境的步骤详解
2020/07/31 Python
介绍一下Linux中的链接
2016/05/28 面试题
4s店市场专员岗位职责
2014/04/09 职场文书
党员先锋岗事迹材料
2014/05/08 职场文书
学生会工作感言
2015/08/07 职场文书
事业单位工作人员岗前培训心得体会
2016/01/08 职场文书