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;
    }
  • 相关阅读:
    mouse_event模拟鼠标滚轮
    润乾报表配置技术路线
    建筑 物件 开心背单词 读句子,单词,字母,看图例, 翻译,看动画
    文字过渡动画,曲线过渡动画,,使用这个插件assign shape keys
    运动锻炼 开心背单词 读句子,单词,字母,看图例, 翻译,看动画,学英语,轻松背单词,简单背单词
    blender293 内置插件 精度绘画控件,PDT学习003,pdt tangents 切线
    日常用品 背单词 读句子 看图片 读单词 读字母 翻译, 看动画 学英语
    blender293 内置插件 精度绘画控件,PDT学习 precision drawing tools
    乔布斯 背单词 02 读句子 单词 字母 翻译,看动画 学英语 名言 我菜顾我在,我菜故我在,blender加python
    狐狸 和 乌鸦 英语 朗读句子 背单词
  • 原文地址:https://www.cnblogs.com/parzulpan/p/9948821.html
Copyright © 2011-2022 走看看