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标准库os.path包、glob包使用实例
Nov 25 Python
Python实现学生成绩管理系统
Apr 05 Python
python微信公众号开发简单流程
Mar 23 Python
基于MTCNN/TensorFlow实现人脸检测
May 24 Python
python3 对list中每个元素进行处理的方法
Jun 29 Python
python通过zabbix api获取主机
Sep 17 Python
Python寻找两个有序数组的中位数实例详解
Dec 05 Python
python3.6生成器yield用法实例分析
Aug 23 Python
Python使用循环神经网络解决文本分类问题的方法详解
Jan 16 Python
python如何通过闭包实现计算器的功能
Feb 22 Python
django实现HttpResponse返回json数据为中文
Mar 27 Python
如何用 Python 制作 GitHub 消息助手
Feb 20 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连接mssql:pdo odbc sql server
2011/07/20 PHP
Yii2实现UploadedFile上传文件示例
2017/02/15 PHP
详解PHP字符串替换str_replace()函数四种用法
2017/10/13 PHP
laravel + vue实现的数据统计绘图(今天、7天、30天数据)
2018/07/31 PHP
google 搜索框添加关键字实现代码
2010/04/24 Javascript
js 操作select和option常用代码整理
2012/12/13 Javascript
Javascript 按位与赋值运算符 (&amp;=)使用介绍
2014/02/04 Javascript
JavaScript中constructor()方法的使用简介
2015/06/05 Javascript
JavaScript中的Math.LOG2E属性使用详解
2015/06/14 Javascript
Web前端框架bootstrap实战【第一次接触使用】
2016/12/28 Javascript
JS去除字符串中空格的方法
2017/02/14 Javascript
使用vue.js写一个tab选项卡效果
2017/03/25 Javascript
利用vscode编写vue的简单配置详解
2017/06/17 Javascript
AngularJS创建一个上传照片的指令实例代码
2018/02/24 Javascript
JavaScript获取移动设备型号的实现代码(JS获取手机型号和系统)
2018/03/10 Javascript
JS实现可针对算术表达式求值的计算器功能示例
2018/09/04 Javascript
mock.js模拟前后台交互
2019/07/25 Javascript
jQuery实现判断滚动条滚动到document底部的方法分析
2019/08/27 jQuery
解决Vue-Router升级导致的Uncaught (in promise)问题
2020/08/07 Javascript
Python实现对百度云的文件上传(实例讲解)
2017/10/21 Python
pandas按若干个列的组合条件筛选数据的方法
2018/04/11 Python
修改 CentOS 6.x 上默认Python的方法
2019/09/06 Python
Python模拟登入的N种方式(建议收藏)
2020/05/31 Python
Python读取xlsx数据生成图标代码实例
2020/08/12 Python
python进度条显示-tqmd模块的实现示例
2020/08/23 Python
LocalStorage记住用户和密码功能
2017/07/24 HTML / CSS
海南地接欢迎词
2014/01/14 职场文书
财务人员岗位职责
2015/02/03 职场文书
外贸英文求职信范文
2015/03/19 职场文书
2015年全民国防教育日活动总结
2015/03/23 职场文书
大学生自我推荐信范文
2015/03/24 职场文书
三八红旗手主要事迹材料
2015/11/04 职场文书
MongoDB数据库的安装步骤
2021/06/18 MongoDB
Python使用openpyxl批量处理数据
2021/06/23 Python
详细聊聊浏览器是如何看闭包的
2021/11/11 Javascript
SpringBoot使用AOP实现统计全局接口访问次数详解
2022/06/16 Java/Android