大位数问题:int的表示范围是 -2147483648~2147483647 。 当两个正数相加的结果大于2147483647时,将会造成越界,而得到负数的结果。同样两个大位数相乘,也会导致越界的危险。为此,处理大位数问题时,普通的做法将无法满足需求。
解决方法主要有两种:
利用现有的大数库。如:GNU MP等。可参考维基百科上的介绍 - GNU多重精度运算库
自己动手写。
大位数加法
思路:
按照小学时算算术题的方法,从最低位开始相加,有进位时先记录下来,在下一位做加法时,加上进位。
/*
大位数加法
作者:Zoo
时间:2016年4月20日21:19:49
*/
#include <iostream>
#include <string>
using namespace std;
/*
num1 : 大位数1,用字符串存储
high1 : 大位数的最高位序号(字符串长度-1)
*/
void multiadd(char * num1, int len1, char * num2, int len2);
int main()
{
char s[] = "991";
char d[] = "19";
multiadd(s, 2, d, 1);
return 0;
}
void multiadd(char * num1, int len1, char * num2, int len2)
{
int i = 0, j = 0;
int flag = 0; //进位标志
string tmp;
while (i <= len1 && j <= len2)
{
int val = (num1[len1 - i++] - '0' + num2[len2 - j++] - '0' + flag);
tmp.append(1, val % 10 + '0');
flag = val / 10;
}
if (i > len1)
{
while (j <= len2)
{
int val = num2[len2 - j++] + flag - '0';
tmp.append(1, val % 10 + '0');
flag = val / 10;
}
}
else if (j > len2)
{
while (i <= len1)
{
int val = num1[len1 - i++] + flag - '0';
tmp.append(1, val % 10 + '0');
flag = val / 10;
}
}
if (flag != 0)
{
tmp.append(1, flag + '0');
}
// 输出
cout << string(tmp.rbegin(), tmp.rend()) << endl;
}
大位数乘法
思路:
同上。关于大位数乘法,还可以利用FFT(傅里叶变换)的原理来解决。
/*
大位数加法
作者:Zoo
时间:2016年4月20日21:19:49
*/
#include <iostream>
#include <string>
using namespace std;
string multi(char * num1, int high1, char * num2, int high2,int cnt);
void stradd(string & res, const string & src);
void result(char * num1, int high1, char * num2, int high2);
int main()
{
result("123", 2, "123", 2);
return 0;
}
string multi(char * num1, int high1, char * num2, int high2, int cnt)
{
string res;
res.append(cnt, 0 + '0');
int flag = 0; //进位标志
while (high1 >= 0)
{
int mul = (num1[high1--] - '0') * (num2[high2] - '0');
res.append(1, (mul % 10 + flag) % 10 + '0');
flag = (mul % 10 + flag) / 10 + mul / 10;
}
return res;
string s(res.rbegin(), res.rend());
cout << s <<endl;
}
void stradd(string & res, const string & src)
{
int len1 = res.length();
int len2 = src.length();
int i = 0, j = 0;
int flag = 0;
string tmp;
while (i < len1 && j < len2)
{
int val = (res[i++] - '0'+ src[j++] - '0' + flag );
tmp.append(1,val % 10 + '0');
flag = val / 10;
}
if (i==len1)
{
while (j < len2)
{
int val = src[j++] + flag - '0';
tmp.append(1, val%10+'0');
flag = val / 10;
}
}
else if (j == len2)
{
while (i < len1)
{
int val = src[i++] + flag - '0';
tmp.append(1, val % 10 + '0');
flag = val / 10;
}
}
if (flag != 0)
{
tmp.append(1, flag + '0');
}
res = tmp;
return ;
}
void result(char * num1, int high1, char * num2, int high2)
{
int i = 0;
string res;
while ( (high2 - i) >= 0)
{
string tmp = multi(num1, high1, num2, high2-i, i);
i++;
stradd(res, tmp);
}
// 输出结果
cout << string(rbegin(res), rend(res)) << endl;
}