第一次自己完整写对,多多指教
算法思路:分治。
第一步:经过预处理将两个整数变为长度一样的两个数(短的在前面补0)
第二部:把两个大整数都平分为前后两部分
第三部:按以下公式计算
(实现大数乘法之前实现了大数加减法)
公式:
X=A*10^(n/2)+B
Y=C*10^(n/2)+D
XY=AC*10^n+((A-B)(D-C)+AC+BD)*10^(n/2)+BD
#include<iostream>
#include<string>
#include<algorithm>
#include<assert.h>
using namespace std;
class BigIntegerCalculate {
private:
static void checkNumber(string numb) {
assert(!numb.empty());
int len = numb.length();
int i = 0;
if (len == 1 && numb[0] == '-') assert(false);
if (numb[0] == '-') i++;
for (; i<len; i++) {
if (!(numb[i] >= '0'&&numb[i] <= '9'))
assert(false);
}
}
static void wipeOffFZERO(string& numb) {
string::iterator it = numb.begin();
if (numb[0] == '-') it++;
for (; it != numb.end();)
if (*it != '0')break;
else it = numb.erase(it);
if (numb.length() == 0)numb = "0";
}
static void mulInit(string& numb1, string& numb2) {
int len1 = numb1.length();
int len2 = numb2.length();
if (numb1[0] == '-') len1--;
if (numb2[0] == '-') len2--;
if (len1 == len2) return;
string temp = "";
if (len1>len2)
{
if (numb2[0] == '-')
{
temp.push_back('-');
numb2 = numb2.substr(1, string::npos);
}
for (int i = 0; i<len1 - len2; i++)
temp.push_back('0');
numb2 = temp + numb2;
}
else {
if (numb1[0] == '-')
{
temp.push_back('-');
numb1 = numb1.substr(1, string::npos);
}
for (int i = 0; i<len2 - len1; i++)
temp.push_back('0');
numb1 = temp + numb1;
}
}
static string add(string numb1, string numb2) {
wipeOffFZERO(numb1);
wipeOffFZERO(numb2);
if (numb1[0] == '-')
{
numb1 = numb1.substr(1, string::npos);
return sub(numb2, numb1);
}
if (numb2[0] == '-')
{
numb2 = numb2.substr(1, string::npos);
return sub(numb1, numb2);
}
string result = "";
int len1 = numb1.length();
int len2 = numb2.length();
int i = len1 - 1, j = len2 - 1, up = 0;
for (; i >= 0 && j >= 0; --i, --j) {
int t = numb1[i] - '0' + numb2[j] - '0' + up;
result.push_back(t % 10 + '0');
up = t / 10;
}
for (; i >= 0; --i) {
int t = numb1[i] - '0' + up;
result.push_back(t % 10 + '0');
up = t / 10;
}
for (; j >= 0; --j) {
int t = numb2[j] - '0' + up;
result.push_back(t % 10 + '0');
up = t / 10;
}
if (up != 0) result.push_back(up + '0');
reverse(result.begin(), result.end());
return result;
}
static string sub(string numb1, string numb2) {
wipeOffFZERO(numb1);
wipeOffFZERO(numb2);
if (numb1[0] == '-')
{
numb1 = numb1.substr(1, string::npos);
return '-' + add(numb2, numb1);
}
if (numb2[0] == '-')
{
numb2 = numb2.substr(1, string::npos);
return add(numb1, numb2);
}
string result = "";
int sign = 1;
int len1 = numb1.length();
int len2 = numb2.length();
string left = numb1, right = numb2;
if (len1<len2 || len1 == len2&&numb1.compare(numb2)<0) {
left = numb2, right = numb1, sign = -1;
int t = len1;
len1 = len2;
len2 = t;
}
int i = len1 - 1, j = len2 - 1, down = 0;
for (; i >= 0 && j >= 0; --i, --j) {
int t = left[i] - right[j] - down;
down = 0;
while (t<0) {
down++;
t += 10;
};
result.push_back(t + '0');
}
for (; i >= 0; --i) {
int t = left[i] - down - '0';
down = 0;
while (t<0) {
down++;
t += 10;
};
result.push_back(t + '0');
}
for (; j >= 0; --j) {
int t = right[i] - down - '0';
down = 0;
while (t<0) {
down++;
t += 10;
};
result.push_back(t + '0');
}
reverse(result.begin(), result.end());
if (sign == -1)
result = '-' + result;
wipeOffFZERO(result);
return result;
}
static void TZERRO(string& numb) {
int len = numb.length();
int i = 0;
if (numb[0] == '-') i++;
for (; i<len; i++)
if (numb[i] != '0') return;
numb = "0";
}
static void Transposition(string& numb, int pos) {
for (int i = 0; i<pos; i++)
numb.push_back('0');
}
static string mul(string numb1, string numb2) {
TZERRO(numb1); TZERRO(numb2);
if (numb1 == "0" || numb2 == "0") return "0";
mulInit(numb1, numb2);
int len = numb1.length();
int a = 1, b = 1;
if (numb1[0] == '-') { a = -1; len--; numb1 = numb1.substr(1, string::npos); }
if (numb2[0] == '-') { b = -1, numb2 = numb2.substr(1, string::npos); }
int sign = a*b;
string result = "";
if (len == 1) {
int t = (numb1[0] - '0')*(numb2[0] - '0');
result.push_back(t % 10 + '0');
if (t / 10 != 0) result = char(t / 10 + '0') + result;
}
else {
string A = numb1.substr(0, len / 2);
string B = numb1.substr(len / 2, string::npos);
string C = numb2.substr(0, len / 2);
string D = numb2.substr(len / 2, string::npos);
string AC = mul(A, C);
string BD = mul(B, D);
string AsubB = sub(A, B);
string DsubC = sub(D, C);
string M = mul(AsubB, DsubC);
M = add(M, AC);
M = add(M, BD);
Transposition(AC, 2 * (len - len / 2));
Transposition(M, len - len / 2);
result = add(AC, M);
result = add(result, BD);
}
if (sign == -1)
result = '-' + result;
return result;
}
public:
static string Add(string numb1, string numb2) {
checkNumber(numb1);
checkNumber(numb2);
return add(numb1, numb2);
}
static string Sub(string numb1, string numb2) {
checkNumber(numb1);
checkNumber(numb2);
return sub(numb1, numb2);
}
static string Mul(string numb1, string numb2) {
checkNumber(numb1);
checkNumber(numb2);
return mul(numb1, numb2);
}
};
int main() {
string numb1, numb2;
cin >> numb1 >> numb2;
cout << BigIntegerCalculate::Mul(numb1, numb2) << endl;
return 0;
}