分治演算法:大整數相乘 字串實現
阿新 • • 發佈:2018-11-12
由於網上大部分用分治演算法實現的大整數相乘程式,其輸入乘數竟然設定為int值,實現了分治思想,但實在不能稱其為大整數。本文實現了用字串儲存乘數,並且輸出正確結果。由於演算法未經過大量資料測試,可能還存在問題,歡迎指教討論,求輕踩。。。
演算法分析:https://www.cnblogs.com/little-kwy/archive/2017/09/30/7613642.html
C++程式碼:
#include <iostream> #include <string> #include <algorithm> 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; }