分治算法步骤:
1. 分解,将要解决的问题划分为若干个规模较小的同类问题
2. 求解,当子问题划分的足够小时,用较简单的方法解决
3. 合并,按原问题的要求,将子问题的解逐层合并构成原始问题的解
对于大整数相乘 需要如下几步:
如 1234 5678
首先进行分解: 取每个数字的一半长度
12 34
56 78
接下来进行单个的运算
12 * 56 (1200 * 5600)
12 * 78 (1200 * 78)
34 * 56 (34 * 5600)
34 * 78 (34 * 78)
最后将计算结果相加,则为最终结果
更大整数的相乘 如:
12345678 23456789
首先进行分解到足够小
1234 5678
2345 6789
继续分解
12 34 56 78
23 45 67 89
接下来进行计算(步骤较多且复杂,但是可以利用递归完成)
对于乘法来说,运算步骤先后不重要,当位数较大时,只需要计算出单个的值
然后在尾后追加0即可。
12 * 23 ((1210^6 ) * (23 * 10^6))
12 * 45 ((12 * 10^6) * (45 * 10 ^ 4))
12 * 67 ((12 * 10 ^ 6) * (67 * 10 ^ 2))
12 * 89 ((12 * 10 ^6) * 89)
34 * 23 ((23 * 10 ^4) * (23 * 10 ^6))
34 * 45 ((23 * 10 ^4) * (45 10 ^4))
34 * 67 ((23 * 10 ^4) * (67* 10 ^2))
34 * 89 ((23 * 10 ^4) * 89))
…
…
78 * 89 (78 * 89)
结束运算,将结果相加则为最终结果
当数值较大时,计算机无法直接完成相加的操作,此时需要判断位数来进行相加操作
更低位的数字与更低位的数字进行相加
当我们已经知道了运算方法时,则可以编写程序了
递归编写:
#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
using namespace std;
char result[1000];
string multi(string a,string b);
string add(string a,string b);
string multi(string a, string b) //对于传递的字符串进行处理
{
if(a.length() <= 2 && b.length() <= 2)
{
int value;
// itoa(atoi(a.c_str()) * atoi(b.c_str()),result,10); //itoa为windows特有的函数,在标准C/C++中不存在
///需要跨平台的话 使用sprintf或者stringstream
value = atoi(a.c_str()) * atoi(b.c_str());
sprintf(result,"%d",value);
return string(result); //转换为string并返回
}
if(a.length() > 2) //当数字长度过长时,取长度的一半
{
int k = a.length() / 2;
string a1 = a.substr(0,k); //取前半部分
string a2 = a.substr(k); //取余下部分
return add(multi(a1,b) + string(a2.length(),'0'),multi(a2,b)); //对于结果进行相加,对于前半部分的计算,需要在尾后位置追加0,满足位数
}
return multi(b,a); //如果当b的长度大于a,那么交换位置进行计算
}
string add(string a,string b) //对于给定的结果进行相加
{
if(a.length() <= 4 && b.length() <= 4) //两位数与两位数相乘最多为4位数
{
int value;
// itoa(atoi(a.c_str())+ atoi(b.c_str()),result,10); //itoa为特定的windows函数,对于标准c/c++是不存在的
value = atoi(a.c_str()) + atoi(b.c_str());
sprintf(result,"%d",value);
return string(result); //转换为string并返回
}
string a1 = "0"; //前半部分
string a2 = a; //其中每次相加为后半部分开始
if(a.length() > 4)
{
a1 = a.substr(0,a.length() -4);
a2 = a.substr(a.length() -4); //每次只相加最后四位
}
string b1 = "0";
string b2 = b;
if(b.length() > 4)
{
b1 = b.substr(0,b.length() - 4);
b2 = b.substr(b.length() -4); //只相加最后四位
}
string s = add(a2,b2); //从低位至高位进行相加
///当出现结果小于四位数的话,比如0123+0234 此时结果只是为三位
if(s.length() < 4 ) string(4 - s.length() ,'0') + s; //添加前置0
///当出现结果大于4位数,则表示需要进位 如 5555 + 6665 此时结果为5位数,此时进一位并忽略掉s中的的第一位
if(s.length() > 4) return add(add(a1,b1),"1") + s.substr(1);
///刚好满足4为时,无需其他操作,继续进行分解
return add(a1,b1) + s;
}