分治法的思路通常的算法教科書上都有,大數相乘也常常用來做爲練習分治思想的很好的例子。算法
具體以下:編程
雖然上面的原理是對應2進制的,可是對於10進制也一樣可行。c#
用C#實現,儘量的利用C#的特性。本例中,只要拆分的數字小於9位數,就能夠直接相乘計算,保證不會溢出。數組
在編程中,還須要用的加法和減法,也要經過字符串模擬實現。ide
最終的乘法運算,依賴遞歸思想得以實現。測試
本文的代碼還有一些能夠優化的地方,好比對於不使用字符串而是所有使用數組,可能會更快點。優化
代碼以下:ui
namespace bigIntMultiply { class Program { static void Main(string[] args) { string a = "99999999999999"; string b = "123456789001234567890"; Stopwatch sw = new Stopwatch(); sw.Start(); string s = Multiply(b, b); sw.Stop(); Console.WriteLine(s); Console.WriteLine(sw.Elapsed); } //字符串模擬乘法操做 static string Multiply(string x, string y) { //deep++;// Console.WriteLine("-" + deep + "-"); string negative = ""; if ((x.StartsWith("-") && y.StartsWith("-")) || (!x.StartsWith("-") && !y.StartsWith("-"))) { x = x.TrimStart('-'); y = y.TrimStart('-'); negative = ""; } else if ((x.StartsWith("-") && !y.StartsWith("-")) || (!x.StartsWith("-") && y.StartsWith("-"))) { x = x.TrimStart('-'); y = y.TrimStart('-'); negative = "-"; } //若是長度都小於9,直接相乘,返回就好了。 if (x.Length <= 9 && y.Length <= 9) { long tmp = (long.Parse(x) * long.Parse(y)); if (tmp == 0) return tmp.ToString(); return negative + (long.Parse(x) * long.Parse(y)).ToString(); } //公式裏的abcd string a, b, c, d; if (x.Length <= 9) { a = "0"; b = x; } else { if (x.Length % 2 != 0) x = "0" + x; a = x.Substring(0, x.Length / 2); b = x.Substring(x.Length / 2); } if (y.Length <= 9) { c = "0"; d = y; } else { if (y.Length % 2 != 0) y = "0" + y; c = y.Substring(0, y.Length / 2); d = y.Substring(y.Length / 2); } int n = x.Length >= y.Length ? x.Length : y.Length; string t1, t2, t3; //遞歸調用,根據公式計算出值。 string ac = Multiply(a, c); string bd = Multiply(b, d); t1 = Multiply(Subtract(a, b), Subtract(d, c)); t2 = Add(Add(t1, ac), bd); t3 = Add(Add(Power10(ac, n), Power10(t2, n / 2)), bd).TrimStart('0'); if (t3 == "") return "0"; return negative + t3; } //字符串模擬加法操做 static string Add(string x, string y) { if (x.StartsWith("-") && !y.StartsWith("-")) { return Subtract(y, x.TrimStart('-')); } else if (!x.StartsWith("-") && y.StartsWith("-")) { return Subtract(x, y.TrimStart('-')); } else if (x.StartsWith("-") && y.StartsWith("-")) { return "-" + Add(x.TrimStart('-'), y.TrimStart('-')); } if (x.Length > y.Length) { y = y.PadLeft(x.Length, '0'); } else { x = x.PadLeft(y.Length, '0'); } int[] sum = new int[x.Length + 1]; for (int i = x.Length - 1; i >= 0; i--) { int tmpsum = int.Parse(x[i].ToString()) + int.Parse(y[i].ToString()) + sum[i + 1]; if (tmpsum >= 10) { sum[i + 1] = tmpsum - 10; sum[i] = 1;//表示進位 } else { sum[i + 1] = tmpsum; } } string returnvalue = string.Concat(sum); if (sum[0] == 1) { return returnvalue; } else { return returnvalue.Remove(0, 1); } } //字符串模擬減法操做 static string Subtract(string x, string y) { //if (x.StartsWith("-") && !y.StartsWith("-")) //{ // return "-" + Add(x.TrimStart('-'), y); //} //if (y.StartsWith("-")) //{ // return Add(x, y.TrimStart('-')); //} //x是正數,y也是正數 int flag = checkBigger(x, y); if (flag == 0) { return "0"; } else if (flag == -1) { string tmp = y; y = x; x = tmp; } //保證了x>=y y = y.PadLeft(x.Length, '0');//y補0與x對齊 int[] difference = new int[x.Length]; for (int i = x.Length - 1; i >= 0; i--) { int tmpdifference; tmpdifference = int.Parse(x[i].ToString()) - int.Parse(y[i].ToString()) + difference[i]; if (tmpdifference < 0) { tmpdifference += 10; difference[i - 1] = -1;//表示借位 } difference[i] = tmpdifference; } StringBuilder returnvalue = new StringBuilder(string.Concat(difference).TrimStart('0')); { if (returnvalue.ToString() == "") { return "0"; } } if (flag == -1) { returnvalue = returnvalue.Insert(0, "-"); } return returnvalue.ToString(); } //比較大小 static int checkBigger(string x, string y) { if (x.Length > y.Length) { return 1; } else if (x.Length < y.Length) { return -1; } else { for (int i = 0; i < x.Length; i++) { if (int.Parse(x[i].ToString()) > int.Parse(y[i].ToString())) { return 1; } else if (int.Parse(x[i].ToString()) < int.Parse(y[i].ToString())) { return -1; } continue; } return 0; } } //模擬移位 static string Power10(string num, int n) { return num.PadRight(num.Length + n, '0'); } } }
測試了一下1234567890.........1234567890(260個1234567890,2600位)的平方,得出的結果以下:spa
能夠從https://defuse.ca/big-number-calculator.htm獲得驗證。pwa