大整数乘法

  • 大整数乘法(1~32位大整数乘法)
    • 分治的思想
    • 实验题目及要求(大整数乘法)
    • 算法分析(result=m4*10^2^+(m2+m3)*10^n/2^+m1)
    • 算法分析
    • 代码
      • 源文件 main.cpp
      • 源文件 mult.cpp
      • 头文件 mult.h
    • 特别说明
    • 运行结果

大整数乘法(1~32位大整数乘法)

保姆级别教程 包学包会

分治的思想

分治算法的思想主要为:分、治、合,基本思想是把一个大问题分解成若干个内容相同或结构相似的小问题,通过不断求解这些小问题,找到出口,最终回到原本的问题上,求得要得到的解。

对于本实验:

设有两个大整数,分别为X、Y,把X、Y均分解成两个位数相同的数,(首先在输入的两个大整数X、Y的高位补零,将大整数补成2的n次方幂位数)再将X、Y各分为两段,每段长为n/2位。则有:
X = B * 10 ^( n / 2 )+ A,Y = D * 10 ^( n / 2 )+ C
这样乘法可变为:
X * Y = B * D * 10 ^ n+( B * C + A * D) 10 ^( n / 2 )+A * C*。
在新得到的式子中,所有两位及以上两数相乘均可拆分成这个式子进行计算。

下面我们来寻找这个分治算法的出口,两个整数相乘,最小是一位数与一位数的乘法,因此该算法的出口应当为一位数与一位数相乘。即将一开始的n位的大整数分解为n/2位的大整数,再将新得到的n/2位的大整数分解为n/4位的大整数,直到k次分解后得到一位的整数,将两个大整数均分解为一位的整数后计算两数相乘的结果,再将结果往回代,直到得到n位数相乘的结果。

这就把两个大整数乘法这个大的问题拆分成了若干个小问题,这些小问题包括乘法和加法,故,在进行算法设计时,要考虑应该设计的子函数应当包括乘法加法。将大整数分解需要进行移位,所以子函数要包含能够实现移位功能的子函数。两个大整数的位数可能不同,为了方便处理,应该将两个大整数补成位数相同的数,所以还需要一个补齐函数。

在设计步骤中,需要的主要函数:

int uniform(int len1,int len2);//求两个数中较长位数
void chartoint(char str1[],int len,int data[]);//字符串转为整数(利用阿斯克码)并将两个大整数补成位数相同的2的幂次方位数的大整数 为了方便加法运算选择逆序储存
void Add(int data1[],int data2[],int result[],int n);//大整数加法
void Move(int data1[],int n);//整数位左移或右移,实现将大整数拆分成两个n/2位的整数
void Multify(int data1[],int data2[],int result[],int n);//大整数乘法

实验题目及要求(大整数乘法)

程序设计语言中的整型数据类型可以存放一定范围内的整数,超出这个范围的大整数就不能再用普通变量存储和操作,这样的整数通常被称为“大整数”。大整数的存储需要借助于数组或链表等,其操作也需要编写程序完成。
要求:
(1) 可实现32位十进制大整数乘法。
(2) 两个大整数相乘如果按照传统的方法,需要耗费n2次数量相乘,试设计大整数乘法的分治算法,要求时间复杂度低于n2阶。
(3) 选择一种高级程序设计语言,实现该算法,要求程序规范,有注释,输出结果正确。

算法分析(result=m4*102+(m2+m3)*10n/2+m1)

1.Multify(data1,data2,result,n)
过程 Multify(data1,data2,result,n)
1.if(data1的长度为1或data2的长度为1) then 做乘法 data1[1] * data2[1]结果储存在result中
2.将data1、data2分成两部分
a←Divide(data1,a,0,n/2)
b←Divide(data1,b,n/2,n)
c←Divide(data2,c,0,n/2)
d←Divide(data2,d,n/2,n)
3.a * c←Multify(a,c,m1,n/2)
a * d←Multify(a,d,m2,n/2)
b * c←Multify(b,c,m3,n/2)
b * d←Multify(b,d,m4,n/2)
4.对m4进行移位
Move(m4,n)
5.m2+m3←Add(m2,m3,tem1,n2);
6.对tem1进行移位
Move(tem1,n/2);
7.m4+tem1←Add(m4,tem1,tem2,n
2);
8.tem2+m1←Add(tem2,m1,result,n*2);

算法分析

空间复杂度分析:设data1,data2分别为两个大整数,|data1|=|data2|=n;设tem为加法所得结果,由加法的特性可知|tem|=n,故算法所需的辅助空间为n。在Multify中,设所得乘法结果为数组result,|result|=n2,故Multify所需的空间为n2

时间复杂度分析:用10n做乘法相当于简单地左移n位,它需要Θ(n)时间。由问题分析可知,乘法公式中需进行4次乘法运算和3次加法运算,则可得到递推式:n=1时,T(n)=d;n>1时,T(n)=4T(n/2)+bn。该递推式中b和d均为大于0的常量。由定理2.5可得:T(n)=Θ(n2)。

代码

源文件 main.cpp

#include <iostream>
#include "string.h"#include "mult.h"
using namespace std;int main()
{char str1[MAX],str2[MAX];int len1,len2,len,i;cout<<"请输入两个大整数";gets(str1);gets(str2);len1 = strlen(str1);len2 = strlen(str2);len = uniform(len1,len2);//获取动态空间int *data1,*data2,*result;data1 = (int *)malloc((len+1)*sizeof(int));//+1:是因为data1[0]储存的数组长度data2 = (int *)malloc((len+1)*sizeof(int));result = (int *)malloc((2*len+1)*sizeof(int));//字符型转化为整数型并对齐chartoint(str1,len,data1);chartoint(str2,len,data2);Multify(data1,data2,result,data2[0]);cout<<result[0]<<endl;for(i = result[0];i>=1;i--) cout<<result[i];return 0;
}

源文件 mult.cpp

#include "mult.h"
#include <iostream>
#include <cstring>
#include "string.h"
#include "math.h"
using namespace std;int uniform(int len1,int len2)//求两个数中较长位数
{int len;len = len1;if(len1<len2)len = len2;return len;
}void chartoint(char str1[],int len,int data[])//字符串转为整数 阿斯科码 逆序储存(方便加法计算)
{int i,m,k,n;m = strlen(str1);//求数组长度//补到齐2的k次方位数k = 0;n = pow(2,k);while(k<=6){if(len<=n) break;k++;n = pow(2,k);}data[0] = n;//数组长度for(i = 0;i < m;i++)data[i+1] = str1[m-1-i]-48;//a = 0,b = 2;for(i = m;i<=data[0];i++)//补零data[i+1] = 0;// for(i = 1;i <= data[0];i++)//检查是否可以对齐//     cout<<data[i]<<' ';// cout<<endl;
}void Add(int data1[],int data2[],int result[],int n)//大整数加法 倒序存(直接倒序相加) n为补位之后的位数也是data1、data2长度
{int i,m;//m表示是否需要进位  n1、n2分别表示data1和data2的长度m = 0;//补零if(data1[0]<n)for(i = 1;data1[0]+i <= n;i++)data1[data1[0]+i] = 0;if(data2[0]<n)for(i = 1;data2[0]+i <= n;i++)data2[data2[0]+i] = 0;data1[0] = n;data2[0] = n;for(i = 1;i<=n;i++){result[i] = (data1[i]+data2[i]+m)%10;if(data1[i]+data2[i]+m>9)m = 1;else       if(data1[i]+data2[i]+m>=0&&data1[i]+data2[i]+m<=9)m = 0;}result[0] = n;//结果长度if(m==1){result[0] = n+1;//结果长度result[result[0]] = 1;//进位为1}
//    for(i = 0;i <= result[0];i++)//检验加法结果
//        cout<<result[i]<<' ';
//    cout<<endl;
}void Move(int data1[],int n)//整数位左移或右移 逆序 右移
{int i;i = 0;for(i=data1[0];i>=1;i--)data1[i+n]= data1[i];for(i = 1;i<=n;i++)data1[i] = 0;data1[0] = data1[0]+n;
//    for(i = 1;i<=data1[0];i++)//检验是否右移!输出后边总多一个0
//      cout<<data1[i]<<' ';
//    cout<<endl;
}void Divide(int data1[],int data2[],int low,int high)//分解 将data1的第low位到high位复制到data2中
{int i;for(i = 1;i <= high - low;i++)data2[i] = data1[low+i];data2[0] = high -low;//for(i = 1;i<=data2[0];i++)//检验是否分解正确//  cout<<data2[i]<<' ';//cout<<endl;
}void Multify(int data1[],int data2[],int result[],int n)//大整数乘法
{int *a,*b,*c,*d,*m1,*m2,*m3,*m4,*tem1,*tem2;a = (int *)malloc((n/2+1)*sizeof(int));b = (int *)malloc((n/2+1)*sizeof(int));c = (int *)malloc((n/2+1)*sizeof(int));d = (int *)malloc((n/2+1)*sizeof(int));int i,m;//n1、n2分别表示data1、data2长度m = 0;//是否需要进位i = 0;//出口if(n==1){result[1]=data1[1]*data2[1];if(result[1]<=9)result[0] = 1;else if(result[1]>=10){result[2]=result[1]/10;result[1]%=10;result[0] = 2;}}//分else{Divide(data1,a,0,n/2);Divide(data1,b,n/2,n);Divide(data2,c,0,n/2);Divide(data2,d,n/2,n);m1 = (int *)malloc((n*2+1)*sizeof(int));m2 = (int *)malloc((n*2+1)*sizeof(int));m3 = (int *)malloc((n*2+1)*sizeof(int));m4 = (int *)malloc((n*2+1)*sizeof(int));tem1 = (int *)malloc((n*2+1)*sizeof(int));tem2 = (int *)malloc((n*2+1)*sizeof(int));//治Multify(a,c,m1,n/2);Multify(a,d,m2,n/2);Multify(b,c,m3,n/2);Multify(b,d,m4,n/2);//合并Move(m4,n);Add(m2,m3,tem1,n*2);Move(tem1,n/2);Add(m4,tem1,tem2,n*2);Add(tem2,m1,result,n*2);}
}

头文件 mult.h

#ifndef MULT_H_INCLUDED
#define MULT_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 64//最多可实现64位大整数*64位大整数
int uniform(int len1,int len2);//求两个大整数中较长位数
void chartoint(char str1[],int len,int data[]);//字符串转为整数
void Add(int data1[],int data2[],int result[],int n);//大整数加法
void Move(int data1[],int n);//整数位左移或右移
void Multify(int data1[],int data2[],int result[],int n);//大整数乘法#endif // MULT_H_INCLUDED

特别说明

为方便读者理解,源文件 mult.cpp中加了一些被注释的代码,这些代码可以实现对每个子函数功能的检验。

运行结果

32位*32位
输出:64为结果位数(含0)
后面为大整数相乘结果

分治算法经典问题---大整数乘法(1~32位大整数乘法)C++相关推荐

  1. JS如何处理超过32位的整数的位运算

    这个问题是已经毕业的学员李佳问到的,本想在网上查一下给他个答案省事.转念一想,如果网上如果他能在网上查到看的明白的方案应该不至于来问我.索性自己给他解一解.因为貌似这个问题还是有点意思的. 首先,要知 ...

  2. 64位计算机 内存,Win7 64位/32位系统支持多大内存?64/32位系统有什么区别?

    Win7 64位/32位系统支持多大内存?计算机上不同的操作系统对内存的支持是有限度的,且因为主板.CPU的存在,这样的限制只会更小,但还在用户可以接受的范围内.想知道什么原因限制了内存极限吗?请看下 ...

  3. 点分十进制字符串IP和32位int整数互转Java实现

    点分十进制字符串IP和32位int整数互转Java实现 比较简单基础的题,可记录和回顾基础. IPv4(4*8)和32位的int整数刚好可以11映射,但由于int整数是有符号的,所以不能直接通过划分为 ...

  4. 只用位运算符将十进制整数转换成32位二进制机器码

    定义函数void DecToBin(int a, char b[33]); 函数功能是将整数a转换为它对应的32位二进制机器数,将32位二进制机器数以字符串形式存于字符数组b(以'\0'字符结束). ...

  5. 整数划分问题(分治算法经典)

    题目描述: 整数划分问题是将一个正整数n拆成一组数连加并等于n的形式,且这组数中的最大加数不大于n. 即:n=n1+n2+-+nk; n1>=n2>=n3->=nk 如整数的6划分为 ...

  6. 一道面试题--两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同

    1.问题说明 十进制4 0100 十进制8 1000二进制不同的 0100 1000有两位不同 正常的算法 1.两个数字与1,拿出两个数字的最后一位,比较是否相同,直到右移32次, for (int ...

  7. 基于X86平台的PC机通过网络发送一个int(32位)整数的字节顺序

    1.字节顺序 字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端.大端两种字节顺序.小端字节序指低字节数据存放在内存低地址处,高字节数据存放在内存高地址处:大端字节序是高字节数据存 ...

  8. linux - resize2fs:新大小太大,无法用32位表示

    我有一个12tbext4分区,我想扩展到18tb.我已将新磁盘添加到RAID中,完成此操作后,我希望重新调整分区大小以占用此新空间.我开始了分区的增长,但是这个过程失败了,因为ext4不能处理大于16 ...

  9. 五大常用经典算法—分治算法

    原文作者:bigsai 原文地址:五大常用算法:一文搞懂分治算法 目录 前言 分治算法介绍 分治算法经典问题 二分搜索 快速排序 归并排序(逆序数) 最大子序列和 最近点对 结语 前言 分治算法(di ...

最新文章

  1. iOS图片精确提取主色调算法iOS-Palette(附源码)
  2. 命名实体识别_用膨胀卷积进行命名实体识别 NER
  3. VTK:Filtering之ExtractVisibleCells
  4. linux下vi的一些简单的操作
  5. linux unshare 命令,详解Linux Namespace之User
  6. 路由器下一跳地址怎么判断_网络基本功三:细说路由器
  7. Linux添加授信根证书,linux系统添加根证书 linux证书信任列表
  8. scrapy简单爬取图片
  9. Num70 债权查询 债权审核
  10. 监管码服务器维修,云风的 BLOG
  11. OpenSSL API: SSL对象和SSL_CTX对象的使用
  12. selenium测试(Java)-- 显式等待(九)
  13. linux中常见的文件操作命令
  14. 基于 DHT 网络的磁力链接和BT种子的搜索引擎架构
  15. python快捷键设置,环境设置、输出print、转义字符、标识符
  16. 小程序tab切换引起的echarts渲染堆积到一块的显示问题(三)
  17. 阿里cdn请求原理以及缓存机制
  18. 【论文笔记】PassGAN: A Deep Learning Approach for Password Guessing
  19. LONG 类型与TO_LOB函数
  20. GitHub使用(详细版)

热门文章

  1. libdmtx库的配置与OpenCV4.5的安装
  2. 好节目推荐---我爱记歌词
  3. win10_1903使用冰点还原出现蓝色修复错误,记一次机房维护日记。
  4. 歌咏比赛,有10个评委,有5个选手,求出每一个选手的平均得分(去掉一个最高分和一个最低分)。 要求:利用数组、有参有返回的函数
  5. 云生态大会,随“峰”而来
  6. 你知道Application吗?
  7. vue 使用addRoutes()合并动态有权路由
  8. c语言算法教学反思,计算机的教学反思
  9. 迈动互联中标北京人寿保险
  10. 白璐:黄海波嫖娼:女主角是双性人还是变性人?