コード例 #1
0
ファイル: AMath.cs プロジェクト: vladdyslav/arbitraryportable
        /// <summary>
        /// Calculates a product of a two ALong instances, a.k.a "School" method (very slow)
        /// </summary>
        /// <param name="num1">Multiplicand</param>
        /// <param name="num2">Multiplier</param>
        /// <returns>Product of num1 and num2.</returns>

        //TODO: replace with Karatsuba, Schönhage–Strassen or Knuth. (Fast Fourier transform?).
        //TODO: use base of size of Int32 to "shorten" sizes of numbers within multiplication speed being kept.
        public static ALong Mul(ALong num1, ALong num2)
        {
            var result = new ALong(0);

            if (num1 == 0 || num2 == 0)
            {
                return(result);
            }
            var carry = 0;

            for (int i = 0; i < num1.Length(); i++)
            {
                var n1    = num1.GetRNumAtIndex(i);
                var res   = String.Empty;
                var n2len = num2.Length();
                carry = 0;
                for (int k = 0; k < n2len; k++)
                {
                    var n2 = num2.GetRNumAtIndex(k);
                    var ns = n1 * n2 + carry;
                    carry = ns / 10;
                    res   = (ns % 10) + res;
                    if (k == n2len - 1 && carry > 0)
                    {
                        res = carry.ToString() + res;
                    }
                }
                var mulres = new ALong(res);
                mulres.MulBase(i);
                result += mulres;
            }
            if (num1.IsNegative != num2.IsNegative)
            {
                result.SetNegative(true);
            }
            return(result);
        }
コード例 #2
0
ファイル: AMath.cs プロジェクト: vladdyslav/arbitraryportable
        /// <summary>
        /// Calculates a quotient and remainder of division of a two ALong instances.
        /// </summary>
        /// <param name="num1">Divident</param>
        /// <param name="num2">Divisor</param>
        /// <returns>A Tuple of Quotient and Remainder.</returns>
        public static Tuple <ALong, ALong> Divide(ALong num1, ALong num2)
        {
            var num2a = Abs(num2);

            if (num2a < Int32.MaxValue)
            {
                return(DivInt(num1, num2.ToString().ToInt()));
            }
            if (num2 == 0)
            {
                throw new ArgumentException("Division by zero");
            }
            if (num1 == 0)
            {
                return(new Tuple <ALong, ALong>(new ALong(0), new ALong(0)));
            }

            var num1a = Abs(num1);

            if (num1a == num2a)
            {
                return(new Tuple <ALong, ALong>(new ALong(1).SetNegative(num1.IsNegative != num2.IsNegative), new ALong(0)));
            }
            if (num1a < num2a)
            {
                return(new Tuple <ALong, ALong>(new ALong(0), new ALong(num1)));
            }

            var b    = 10; // base
            var down = new ALong(0);

            // Get upper limit
            var up = new ALong(b);

            while (num1a > num2a * up)
            {
                up = up * b;
            }

            // Divide
            while (up - down > 1)
            {
                var cur = (down + up) / 2;
                var c   = num2a * (cur);
                if (c < num1a)
                {
                    down = cur; continue;
                }
                if (c > num1a)
                {
                    up = cur; continue;
                }
                if (c == num1a)
                {
                    down = cur; up = cur; continue;
                }
            }

            var remainder = num1a - down * num2a;

            down.SetNegative(num1.IsNegative != num2.IsNegative);
            remainder.SetNegative(num1.IsNegative);
            return(new Tuple <ALong, ALong>(down, remainder));
        }