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; }