华为经典面试题---大数乘法的c++实现

32位机器上的最大有符号数为2147483647,最大无符号数是4294967295。这对于实际的计算显然是不够的,于是就产生了大数乘法的需求。其思路不算难,按照我们平时计算两个数的乘积的流程就行了。如果你使用的是c语言等不能动态扩展数组的语言,有一个需要考虑的问题是:两数相乘后的位数为多少?这需要一点点的数学知识,两数乘积的位数不大于两数的位数之和。所以需要提前分配好足够的空间。我这里使用c++来实现,不考虑此问题。

思路:

  1. 从较短的数的各位开始循环(外层循环次数少,有利于提高效率),用短数的各位去逐个乘以长数的每个位,得到一个乘积,内层循环结束;取短数的十位,逐个乘以长数的每一位,再次得到一个乘积,用之前的乘积累加上这次的乘积;如此以往,直至外层循环结束,最后加上进位位,得到最终结果。

下面来看代码:

#include 
using namespace std;

string BigIntAdd(string &tmp, string &ret)
{
    int lena = tmp.length();
    int lenb = ret.length();
    const char* pa = tmp.c_str();
    const char* pb = ret.c_str();
    int i = lena - 1;
    int j = lenb - 1;
    int carry = 0;
    string addup;
    while(i >= 0 || j >= 0)
    {
        int sum = 0;
        if(i >= 0)
        {
            sum += pa[i]-0x30;
            i--;
        }
        if(j >= 0)
        {
            sum += pb[j]-0x30;
            j--;
        }
        sum += carry;
        addup = to_string(sum % 10) + addup;
        carry = sum / 10;
    }
    if(carry)
        addup = to_string(carry) + addup;
    return addup;
}

string BigIntTimes(string &a, string &b)
{
    int lena = a.length();
    int lenb = b.length();
    int shoter = 0;
    int longer = 0;
    const char* pshoter;
    const char* plonger;
    if(lena > lenb)
    {
        shoter = lenb;
        longer = lena;
        pshoter = b.c_str();
        plonger = a.c_str();
    }
    else
    {
        shoter = lena;
        longer = lenb;
        pshoter = a.c_str();
        plonger = b.c_str();
    }
    string tmp;
    string ret = "0";
    int zero = 0;
    for(int i = shoter-1; i >= 0; i--)
    {
        int blow = pshoter[i]-0x30;
        int carry = 0;
        int product = 0;
        tmp.append(zero++, '0');
        for(int j = longer-1; j >= 0; j--)
        {
            product = blow * (plonger[j]-0x30) + carry;
            tmp = to_string(product % 10) + tmp;
            carry = product / 10;
        }
        if(carry)
            tmp = to_string(carry) + tmp;
        ret = BigIntAdd(tmp, ret);
        tmp.clear();
    }
    return ret;
}

int main(int argc, char const *argv[])
{
    string a;
    string b;
    if(argc == 3)
    {
        a.assign(argv[1]);
        b.assign(argv[2]);
    }
    cout << "BigIntTimes: " << BigIntTimes(a, b) << endl;
    return 0;
}

注意到函数string BigIntTimes(string &a, string &b)负责计算乘积,但要实现此函数,先要实现一个大数加法的函数string BigIntAdd(string &tmp, string &ret),思路类似,但更简单。

测试

该题原题让求1234567891011121314151617181920 * 2019181716151413121110987654321两数的乘积,
我们先用python算出正确结果,结果为2492816912877266687794240983772975935013386905490061131076320,如下图:
华为经典面试题---大数乘法的c++实现_第1张图片
实际计算的结果如下图:
really
计算结果正确!

你可能感兴趣的:(算法问题)