1. 程式人生 > >大數問題之大數相加、相乘。

大數問題之大數相加、相乘。

部落格轉自:https://blog.csdn.net/hacker00011000/article/details/51298294 若侵權告知立刪!

1. 大數相加
1、從結尾開始每位相加
2、兩個整數長度不相等(肯定有一個已經加完了,再把沒有加完的加上去)
3、最高位有進位,要再進一位
4、結果字串逆序

2. 大數相乘
- 分析
12*34=?
乘數:12
被乘數:34
1、先把乘數列出來,第i行列左起第i位數,列N次(N為乘數的位數)
第二行起每次右移一位

(1) (1)
    (2) (2)

2、寫入被乘數,按先列後行的方式

(1,3) (1,4)
      (2,3) (2
,4)

3、將()內的數兩乘

(1,3=3) (1,4=4)
        (2,3=6) (2,4=8)

4、相加,注意進位

(1,3=3) (1,4=4)
        (2,3=6) (2,4=8)
-------------------------
     3      10       8
         .          
-------------------------
     4       0       8
--------------------- 
作者:silentsharer 
來源:CSDN 
原文:https:
//blog.csdn.net/hacker00011000/article/details/51298294 版權宣告:本文為博主原創文章,轉載請附上博文連結!

12*34=408

再看三位數乘法 
123*456=? 
第一步:

(1) (1) (1)
    (2) (2) (2)
        (3) (3) (3) 

第二步:

(1,4) (1,5) (1,6)
      (2,4) (2,5) (2,6)
            (3,4) (3,5) (3,6)

第三步:

(1,4= 4) (1,5= 5) (1,6= 6)
         (
2,4= 8) (2,5=10) (2,6=12) (3,4=12) (3,5=15) (3,6=18)

第四步:

(1,4= 4) (1,5= 5) (1,6= 6)
         (2,4= 8) (2,5=10) (2,6=12)
                  (3,4=12) (3,5=15) (3,6=18)
----------------------------------------------
      4       13       28       27       18
           .        .        .        .
----------------------------------------------
      5        6        0        8        8     
--------------------- 

123*456=56088
分析一下每一位的值是如何計算出來的,以下說的位都是從個位算起:

結果的第i位,是乘數的第i位乘以被乘數的1位,再加上乘數的第i-1位乘以被乘數的第2位,一起加到乘數的第1位乘以被乘數的第i位。
這樣描述起來有點不明白,畫個圖就很清楚了:
123*456的第3位:從乘數的第3位(1)起到第1位(3),按從右向左的方式
逐個乘以被乘數:
1*6+2*5+3*4=28
再把進位加上就可以了。
即:計算結果的第i位(權值肯定為i,第1位也就是個位權值為0(pow(10, 0)))。等於乘數的第(i~0)位分別與被乘數的第(0~i)位相乘,因為這樣每位相乘之後權值仍為i 。然後相加再加上前一位的進位,就是結果的第i位
到這裡,已經可以得出一個通用的計算方法,把結果逐位計算出來。
通過上面的分析,我們知道了演算法的核心思想,接下來就能把演算法實現
程式程式碼:

#include <iostream>
#include <sstream>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;

//C++大數相加
string BigNumAdd(const string& strNum1, const string& strNum2)
{
    string strSum;
    int len1 = strNum1.size()-1;
    int len2 = strNum2.size()-1;
    int bit = 0;                //儲存進位

    //從結尾開始每位相加 
    while (len1>=0 && len2>=0)
    {
        //求每位的和(要把進位也加上) 
        int tmpSum = strNum1[len1]-'0' + strNum2[len2]-'0' + bit;
        //儲存進結果 
        strSum += tmpSum % 10 + '0';
        //求進位 
        bit = tmpSum / 10;
        --len1;
        --len2; 
    }

    //兩個整數長度不相等(肯定有一個已經加完了,不需要再額外加if來判斷,因為while就可以判斷)
    while (len1 >= 0)
    {
        //和上個while迴圈一樣
        int tmpSum = strNum1[len1]-'0' + bit;
        strSum += tmpSum % 10 + '0';
        bit = tmpSum / 10;
        --len1; 
    }
    while (len2 >= 0) 
    {
        //和上個while迴圈一樣
        int tmpSum = strNum2[len2]-'0' + bit;
        strSum += tmpSum % 10 + '0';
        bit = tmpSum / 10;
        --len2; 
    }

    //最高位有進位
    if (bit != 0)
        strSum += bit + '0'; 

    //反轉
    reverse(strSum.begin(), strSum.end()); 

    return strSum;
}

//C++大數相乘
string BigNumMultiply(const string& strNum1, const string& strNum2)
{
    string strMultiply;
    //兩數相乘最大有m+n位
    int bit = 0;
    int len1 = strNum1.size()-1;
    int len2 = strNum2.size()-1;

    //計算每一位 
    for (int i=0; i<len1+len2+2; ++i)
    {
        //計算結果的第i位(權值肯定為i,第1位也就是個位權值為0(pow(10, 0))) 
        //等於乘數的第(i~0)位分別與被乘數的第(0~i)位相乘,因為這樣每位相乘之後權值仍為i 
        //然後相加再加上前一位的進位,就是結果的第i位
        //然後%10得出第i位,/10得到進位
        int tmp = 0;
        for (int j=i; j>=0; --j)
        {
            //如果下標超出字串的範圍   j為num1的下標, i-j為num2的下標,然後兩數相乘 
            if (j>len1 || (i-j)>len2)
                continue;

            //還要注意字串數字的最高位在字串的最低位所以得用len減去 
            tmp += (strNum1[len1-j]-'0') * (strNum2[len2-(i-j)]-'0');
        }
        //加上進位
        tmp += bit;
        //為了防止最後一位是0,但是卻加上了
        if (tmp == 0 && i == len1+len2+1) 
            break;
        //求餘得到結果的第i位
        strMultiply += tmp % 10 + '0';
        //計算新的進位
        bit = tmp / 10; 
    }

    //判斷結果的最後一個字元如果是0的話說明可以刪去
    //if (strMultiply[strMultiply.size()-1] == '0')
    //  strMultiply[strMultiply.size()-1] = '\0';

    //反轉
    reverse(strMultiply.begin(), strMultiply.end()); 

    return strMultiply;
}

int main()
{
    string str1;
    string str2;
    cin >> str1 >> str2;

    //相加和相乘
    cout << BigNumAdd(str1, str2) << endl;
    cout << BigNumMultiply(str1, str2) << endl; 

    int n;
    cin >> n;

    //階乘 
    string rlt("1");
    string opNum;
    for (int i=1; i<=n; ++i)
    {
        //ss不可以定義在for迴圈外
        stringstream ss; 
        ss << i;
        ss >> opNum;

        rlt = BigNumMultiply(rlt, opNum); 
    }
    cout << rlt << endl;

    return 0;
}