对于分治法求大整数相乘代码以及思路

分治算法步骤:

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;
}

猜你喜欢

转载自blog.csdn.net/David_TD/article/details/84060749
今日推荐