zoukankan      html  css  js  c++  java
  • 计算机考研复试真题 大数问题之大数相加、相乘。

    博客转自: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] = '';
    
        //反转
        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;
    }
  • 相关阅读:
    线段树题胡乱整理
    【テンプレート】RMQ
    【説明する】线段树
    【テンプレート】字符串hash
    [HDOJ3718]Similarity(KM算法,二分图最大匹配)
    [HDOJ3714]Error Curves(三分)
    [HDOJ3711]Binary Number(枚举)
    [HDOJ3709]Balanced Number(数位dp)
    [HDOJ5542]The Battle of Chibi(DP,树状数组)
    [HDOJ5543]Pick The Sticks(DP,01背包)
  • 原文地址:https://www.cnblogs.com/parzulpan/p/9948821.html
Copyright © 2011-2022 走看看