32位机器上的最大有符号数为2147483647,最大无符号数是4294967295。这对于实际的计算显然是不够的,于是就产生了大数乘法的需求。其思路不算难,按照我们平时计算两个数的乘积的流程就行了。如果你使用的是c语言等不能动态扩展数组的语言,有一个需要考虑的问题是:两数相乘后的位数为多少?这需要一点点的数学知识,两数乘积的位数不大于两数的位数之和。所以需要提前分配好足够的空间。我这里使用c++来实现,不考虑此问题。
思路:
- 从较短的数的各位开始循环(外层循环次数少,有利于提高效率),用短数的各位去逐个乘以长数的每个位,得到一个乘积,内层循环结束;取短数的十位,逐个乘以长数的每一位,再次得到一个乘积,用之前的乘积累加上这次的乘积;如此以往,直至外层循环结束,最后加上进位位,得到最终结果。
下面来看代码:
#include <iostream>
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,如下图:
实际计算的结果如下图:
计算结果正确!