分治法實現大數相乘 C#實現

分治法的思路通常的算法教科書上都有,大數相乘也常常用來做爲練習分治思想的很好的例子。算法

具體以下:編程

p_w_picpath

雖然上面的原理是對應2進制的,可是對於10進制也一樣可行。c#

745F289E368648A38856C963432419F4

用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

相關文章
相關標籤/搜索