1.模拟手算
由于计算64位整数乘法,故需要类型为字符串的存储类型。
1.1数字转字符串:
/*----------数字转字符串--------*/
string num2str(int i)
{
stringstream ss;
ss << i;
return ss.str();
}
1.2 字符串转数字
/*---------字符串转数字---------*/
int str2num(string s)
{
int num;
stringstream ss(s);
ss >> num;
return num;
}
1.3高位减0
string minus0(string str)
{
int zeros = 0;
string result;
for(int i = 0; i < str.size(); i++)
{
if(str[i] != '0')
{
zeros = i;
break;
}
}
result = str.substr(zeros);
return result;
}
1.4 采用Karatsuba的算法计算。
/*---------递归乘法-----------*/
string karatsuba(string s1, string s2)
{
int size1 = s1.size();
int size2 = s2.size();
int max = Max(size1, size2);
int half;
if(max % 2 == 0)
{
half = max / 2;
} else {
half = max / 2;
}
string a, b, c , d;
string ac, bd, bc, ad;
string result, temp1, temp2, temp3;
if(max == size1) {
s2 = string(max - size2, '0') + s2;
} else {
s1 = string(max - size1, '0') + s1;
}
if (max == 1)
{
return easymul(s1, s2);
}
a = s1.substr(0, half);
b = s1.substr(half);
c = s2.substr(0, half);
d = s2.substr(half);
ac = karatsuba(a,c);
bd = karatsuba(b,d);
bc = karatsuba(b,c);
ad = karatsuba(a,d);
temp1 = ac + string((max - half) * 2, '0');
temp2 = invertstring(addstring(bc, ad)) + string(max - half,'0');
temp3 = invertstring(addstring(temp1, temp2));
result = invertstring(addstring(temp3, bd));
return result;
}
1.5.完整代码:
#include <iostream>
#include <string>
#include <sstream>
#include <cmath>
#include <time.h>
using namespace std;
string karatsuba(string s1, string s2);
string addstring(string s1, string s2);
string invertstring(string str);
int Max(int x, int y);
string easymul(string s1, string s2);
int str2num(string s);
string minus0(string str);
string num2str(int i);
/*----------数字转字符串--------*/
string num2str(int i)
{
stringstream ss;
ss << i;
return ss.str();
}
/*---------字符串转数字---------*/
int str2num(string s)
{
int num;
stringstream ss(s);
ss >> num;
return num;
}
int Max(int x, int y)
{
return x > y ? x : y;
}
string easymul(string s1, string s2)
{
int num = str2num(s1) * str2num(s2);
return num2str(num);
}
string invertstring(string str)
{
string result;
for(int i = str.size() - 1; i >= 0; i--)
{
result = result + str[i];
}
return result;
}
string addstring(string s1, string s2)
{
int max;
string result;
int addflag = 0;
int temp = 0;
if(s1.size() > s2.size())
{
max = s1.size();
s2 = string(max - s2.size(), '0') + s2;
} else {
max = s2.size();
s1 = string(max- s1.size(), '0') + s1;
}
for(int i = max - 1; i >= 0; i--)
{
temp = (s1[i] - '0') + (s2[i] - '0') + addflag;
if(temp >= 10)
{
addflag = temp / 10;
temp = temp % 10;
} else {
addflag = 0;
}
result = result + num2str(temp);
}
if(addflag != 0)
{
result = result + num2str(addflag);
}
return result; //需要倒序
}
string minus0(string str)
{
int zeros = 0;
string result;
for(int i = 0; i < str.size(); i++)
{
if(str[i] != '0')
{
zeros = i;
break;
}
}
result = str.substr(zeros);
return result;
}
/*---------递归乘法-----------*/
string karatsuba(string s1, string s2)
{
int size1 = s1.size();
int size2 = s2.size();
int max = Max(size1, size2);
int half;
if(max % 2 == 0)
{
half = max / 2;
} else {
half = max / 2;
}
string a, b, c , d;
string ac, bd, bc, ad;
string result, temp1, temp2, temp3;
if(max == size1) {
s2 = string(max - size2, '0') + s2;
} else {
s1 = string(max - size1, '0') + s1;
}
if (max == 1)
{
return easymul(s1, s2);
}
a = s1.substr(0, half);
b = s1.substr(half);
c = s2.substr(0, half);
d = s2.substr(half);
ac = karatsuba(a,c);
bd = karatsuba(b,d);
bc = karatsuba(b,c);
ad = karatsuba(a,d);
temp1 = ac + string((max - half) * 2, '0');
temp2 = invertstring(addstring(bc, ad)) + string(max - half,'0');
temp3 = invertstring(addstring(temp1, temp2));
result = invertstring(addstring(temp3, bd));
return result;
}
int main()
{
clock_t start_time, end_time;
start_time = clock();
string s1 = "1234567890123456789012345678901234567890";
string s2 = "1234567890123456789012345678901234567890";
cout << minus0(karatsuba(s1,s2)) << endl;
end_time = clock();
cout << "total time:" << (double)(end_time - start_time) << endl;
return 0;
}
2. 还写了一个模拟手算的大数乘法.
#include <iostream>
#include <sstream>
#include <string>
#include <time.h>
using namespace std;
string oneline(char a, string str);
string add0(int a)
{
return string(a,'0');
}
string num2str(int a)
{
stringstream ss;
ss << a;
return ss.str();
}
string addstring(string s1, string s2)
{
int max;
string result;
int addflag = 0;
int temp = 0;
if(s1.size() > s2.size())
{
max = s1.size();
s2 = s2 + add0(max - s2.size());
}else {
max = s2.size();
s1 = s1 + add0(max - s1.size());
}
for(int i = 0; i < max; i++)
{
temp = (s1[i] - '0') + (s2[i] - '0') + addflag;
if(temp >= 10)
{
addflag = temp / 10 ;
temp = temp % 10;
} else {
addflag = 0;
}
result = result + num2str(temp);
}
if(addflag != 0)
{
result = result + num2str(addflag);
}
return result; //不需要倒序
}
string multiply(string s1, string s2)
{
string result;
for(int i = s1.size() - 1; i >= 0; i--)
{
string temp = add0(s1.size() - 1 - i) + oneline(s1[i], s2);
result = addstring(temp,result);
}
return result;
}
string oneline(char a, string str2)
{
string result;
int num = 0;
int addflag = 0;
for(int i = str2.size() - 1; i >= 0; i--)
{
num = (a - '0') * (str2[i] - '0') + addflag;
if (num >= 10)
{
addflag = num / 10;
num = num % 10;
} else {
addflag = 0;
}
result = result + num2str(num);
}
if(addflag != 0)
{
result += num2str(addflag);
}
return result; //需要倒序
}
//-----------------高位减0-----------
string minus0(string str)
{
int zeros = 0;
string result;
for(int i = str.size() - 1; i >= 0; i--)
{
if(str[i] != '0')
{
zeros = i;
break;
}
}
for (int j = zeros; j >= 0; j--)
{
result = result + str[j];
}
return result;
}
int main()
{
clock_t start_time, end_time;
start_time = clock();
string s1 = "1234567890123456789012345678901234567890";
string s2 = "1234567890123456789012345678901234567890";
string result;
result = minus0(multiply(s1,s2));
cout << "result::" << result << endl;
end_time = clock();
cout << "total time:" << (double)(end_time - start_time) << endl;
return 0;
}