由于网上大部分用分治算法实现的大整数相乘程序,其输入乘数竟然设定为int值,实现了分治思想,但实在不能称其为大整数。本文实现了用字符串存储乘数,并且输出正确结果。由于算法未经过大量数据测试,可能还存在问题,欢迎指教讨论,求轻踩。。。
算法分析:https://www.cnblogs.com/little-kwy/archive/2017/09/30/7613642.html
下面的函数均为分治函数设置,因为分治后得到的m1,m2,m3如果足够大,就有必要解决他们之间的加减乘等问题,即是字符串的大数相加、相减问题,而由于字符串可能为负数,所以进行运算之前还要加以判断。
C++代码:
#include
#include
#include
using namespace std;
string cut(string s) { //截取一个字符串前面多余的0
int i = 0, length = s.length();
for (i = 0; i < length-1; i++)
if (s[i] != '0')
break;
s = s.substr(i, length);
return s;
}
string add(string a, string b) { //加法,a,b均为正值
string s;
a = cut(a);
b = cut(b);
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
int count = 0, num, t, max_length, a_length = a.length(), b_length = b.length();
max_length = a_length;
if (max_length < b_length) max_length = b_length;
t = 0;
while (count < max_length) {
num = 0;
if (count < a_length) num += (a[count]-'0');
if (count < b_length) num += (b[count]-'0');
s += (t+num)%10+'0';
t = (t+num)/10;
count++;
}
while (t != 0) {
s += (t%10)+'0';
t /= 10;
}
reverse(s.begin(), s.end());
return s;
}
string sub(string a, string b) { //减法,a,b均为正值,且a一定大于等于b
string s;
a = cut(a);
b = cut(b);
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
int count = 0, num, max_length, b_length = b.length();
max_length = b_length;
while (count < max_length) {
num = 0;
if (a[count] >= b[count]) num = a[count]-b[count];
else {
num = 10+a[count]-b[count];
int t = count+1; //向前取位
while (a[t] == '0') {
a[t] = '9';
t++;
}
a[t]--;
}
s += (num+'0');
count++;
}
s += a.substr(count, a.length());
count = a.length()-1;
while (s[count] == '0' && count != 0) count--;
s = s.substr(0,count+1);
reverse(s.begin(), s.end());
return s;
}
string ten_n(string s, int n) { //计算s乘上n个10
while (n--) s += '0';
return s;
}
bool compare(string a, string b) { //判断a、b绝对值的大小,b大返回0,否则返回1
if (a[0] == '-') a = a.substr(1,a.length());
if (b[0] == '-') b = b.substr(1,b.length());
if (a.length() > b.length()) return 1;
else if (a.length() < b.length()) return 0;
else {
int count = a.length();
for (int i = 0; i < count; i++) {
if (a[i] > b[i]) return 1;
else if (a[i] < b[i]) return 0;
}
return 1;
}
}
string expand_first(string a, string b, string c) { //拓展函数1,避免代码重用
string s = add(b,c);
a = a.substr(1,a.length());
if (compare(s,a) == 1) s = sub(s,a);
else s = '-' + sub(a,s);
return s;
}
string expand_second(string a, string b, string c) { //拓展函数2,避免代码重用
string s;
b = b.substr(1,b.length());
c = c.substr(1,c.length());
s = add(b,c);
if (compare(a,s) == 1) s = sub(a,s);
else s = '-' + sub(s,a);
return s;
}
string add_three_number(string a, string b, string c) { //输入三个数,求和,要考虑正负值的情况
if (a[0] != '-' && b[0] != '-' && c[0] != '-') return add(add(a,b),c);
else if (a[0] == '-' && b[0] != '-' && c[0] != '-') return expand_first(a,b,c);
else if (a[0] != '-' && b[0] == '-' && c[0] != '-') return expand_first(b,a,c);
else if (a[0] != '-' && b[0] != '-' && c[0] == '-') return expand_first(c,a,b);
else if (a[0] == '-' && b[0] == '-' && c[0] != '-') return expand_second(c,a,b);
else if (a[0] == '-' && b[0] != '-' && c[0] == '-') return expand_second(b,a,c);
else if (a[0] != '-' && b[0] == '-' && c[0] == '-') return expand_second(a,b,c);
else return '-'+add(add(a,b),c);
}
string mult(string X, string Y, int n) {
int flag = 1, note = 0;
string S;
if (X[0] == '-') {
flag = flag * (-1);
X = X.substr(1, X.length());
}
if (Y[0] == '-') {
flag = flag * (-1);
Y = Y.substr(1, Y.length());
}
for (int i = 0; i < n; i++) //由于一开始输入可能会补0,加上此判断
if (X[i] != '0') {
note++; break;
}
for (int i = 0; i < n; i++)
if (Y[i] != '0') {
note++; break;
}
if (note != 2)
return "0";
else if (n == 1) {
int num = (X[0]-'0')*(Y[0]-'0');
while (num != 0) {
S += (num%10+'0');
num /= 10;
}
reverse(S.begin(), S.end());
if (flag == 1) return S;
else {
S = '-' + S;
return S;
}
} else {
string A,B,C,D,E,F,m1,m2,m3;
A = X.substr(0, n/2);
B = X.substr(n/2, n);
C = Y.substr(0, n/2);
D = Y.substr(n/2, n);
// cout << A << ' ' << B << ' ' << C << ' ' << D << endl;
m1 = mult(A, C, n/2);
if (compare(A,B) == 1) E = sub(A,B); //由于要判断数的正负,而函数的功能有限,特此分解开来求解
else E = '-' + sub(B,A);
if (compare(D,C) == 1) F = sub(D,C);
else F = '-' + sub(C,D);
m2 = mult(E, F, n/2);
m3 = mult(B, D, n/2);
S = add_three_number(ten_n(m1, n), ten_n(add_three_number(m1, m2, m3), n/2), m3);
if (flag == 1) return S;
else {
S = '-' + S;
return S;
}
}
}
int main() {
string X, Y;
int n, dis, max_length, x_length, y_length;
while (cin >> X >> Y, X != "-1") { //自动生成n算了....
n = 2;
x_length = X.length(), y_length = Y.length();
x_length > y_length ? max_length = x_length : max_length = y_length;
while (n < max_length) n = n * 2;
while (x_length < n) {
x_length++;
X = '0' + X;
}
while (y_length < n) {
y_length++;
Y = '0' + Y;
}
cout << mult(X,Y,n) << endl;
}
return 0;
}