예제 #1
0
        public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder)
        {
            remainder = null;
            if (dividend == null || divisor == null)
            {
                return(null);
            }
            if (divisor.sign == 0)
            {
                throw new DivideByZeroException();
            }
            if (dividend.AbsCompareTo(divisor) < 0)
            {
                remainder = new BigInteger(dividend);
                return(0);
            }
            BigInteger quotient = new BigInteger();

            remainder      = new BigInteger();
            quotient.data  = new byte[dividend.data.Length - divisor.data.Length + 1];
            remainder.data = new byte[divisor.data.Length];
            BigArithmetic.DivRem(quotient.data, remainder.data, dividend.data,
                                 dividend.data.Length, divisor.data, divisor.data.Length);
            quotient.sign  = (sbyte)(dividend.sign * divisor.sign);
            remainder.sign = dividend.sign;
            quotient.Shrink();
            remainder.Shrink();
            return(quotient);
        }
예제 #2
0
        public static BigInteger operator +(BigInteger x, BigInteger y)
        {
            if (x == null || y == null)
            {
                return(null);
            }
            if (x.AbsCompareTo(y) < 0)
            {
                Utility.Swap(ref x, ref y);
            }
            BigInteger z = new BigInteger();

            z.sign = x.sign;
            byte[] bs    = Utility.Expand(y.data, x.data.Length);
            bool   isAdd = x.sign * y.sign == 1;

            z.data = new byte[x.data.Length + (isAdd ? 1 : 0)];
            if (isAdd)
            {
                BigArithmetic.Add(z.data, x.data, bs, bs.Length);
            }
            else
            {
                BigArithmetic.Subtract(z.data, x.data, bs, bs.Length);
            }
            z.Shrink();
            return(z);
        }
예제 #3
0
        //= pp.780-781, mppi, 20.6 任意精度的运算
        /// <summary>
        /// 计算圆周率到小数点后 digits 位数字。
        /// 计算结果保存在返回的字节数组中,每个字节存放两个十进制数字,字节数组的第一个元素是“03”。
        /// 字节数组的长度可能大于 (digits + 1) / 2 + 1,只保证小数点后前 digits 个十进制数字是准确的。
        /// </summary>
        /// <param name="digits">小数点后的十进制数字个数</param>
        /// <returns>存放圆周率的字节数组</returns>
        public static byte[] Compute(int digits)
        {
            if (digits < 0)
            {
                throw new ArgumentOutOfRangeException("digits", "can't less than zero");
            }
            int n = Math.Max(5, (digits + 1) / 2 + 2);

            byte[] pi = new byte[n + 1];
            byte[] x  = new byte[n + 1], y = new byte[n << 1];
            byte[] sx = new byte[n], sxi = new byte[n];
            byte[] t  = new byte[n << 1], s = new byte[3 * n];
            t[0] = 2;                             // t = 2
            BigArithmetic.Sqrt(x, x, n, t, n);    // x = sqrt(2)
            BigArithmetic.Add(pi, t, x, n);       // pi = 2 + sqrt(2)
            Array.Copy(pi, 1, pi, 0, n);
            BigArithmetic.Sqrt(sx, sxi, n, x, n); // sx = sqrt(x)
            Array.Copy(sx, y, n);                 // y = sqrt(x)
            for (; ;)
            {
                BigArithmetic.Add(x, sx, sxi, n);       // x = sqrt(x) + 1/sqrt(x)
                Array.Copy(x, 1, x, 0, n);
                BigArithmetic.Divide(x, x, n, 2);       // x = x / 2
                BigArithmetic.Sqrt(sx, sxi, n, x, n);   // sx = sqrt(x), sxi = 1/sqrt(x)
                BigArithmetic.Multiply(t, y, n, sx, n); // t = y * sx
                Array.Copy(t, 1, t, 0, n);
                BigArithmetic.Add(t, t, sxi, n);        // t = y * sx + sxi
                x[0]++;
                y[0]++;
                BigArithmetic.Inverse(s, n, y, n);      // s = 1 / (y + 1)
                Array.Copy(t, 1, t, 0, n);
                BigArithmetic.Multiply(y, t, n, s, n);  // y = t / (y + 1)
                Array.Copy(y, 1, y, 0, n);
                BigArithmetic.Multiply(t, x, n, s, n);  // t = (x + 1) / (y + 1)
                int mm = t[1] - 1;                      // 若 t == 1 则收敛
                int j  = t[n] - mm;
                if (j > 1 || j < -1)
                {
                    for (j = 2; j < n; j++)
                    {
                        if (t[j] != mm)
                        {
                            Array.Copy(t, 1, t, 0, n);
                            BigArithmetic.Multiply(s, pi, n, t, n); // s = t * pi
                            Array.Copy(s, 1, pi, 0, n);             // pi = t * pi
                            break;
                        }
                    }
                    if (j < n)
                    {
                        continue;
                    }
                }
                break;
            }
            return(pi);
        }
예제 #4
0
 int AbsCompareTo(BigInteger other)
 {
     if (data.Length < other.data.Length)
     {
         return(-1);
     }
     if (data.Length > other.data.Length)
     {
         return(1);
     }
     return(BigArithmetic.Compare(data, other.data, data.Length));
 }
예제 #5
0
        public static BigInteger operator *(BigInteger x, BigInteger y)
        {
            if (x == null || y == null)
            {
                return(null);
            }
            if (x.sign * y.sign == 0)
            {
                return(0);
            }
            BigInteger z = new BigInteger();

            z.sign = (sbyte)(x.sign * y.sign);
            z.data = new byte[x.data.Length + y.data.Length];
            BigArithmetic.Multiply(z.data, x.data, x.data.Length, y.data, y.data.Length);
            z.Shrink();
            return(z);
        }
예제 #6
0
        public static BigInteger Sqrt(BigInteger x)
        {
            if (x == null || x.sign < 0)
            {
                return(null);
            }
            if (x.sign == 0)
            {
                return(0);
            }
            if (x.data.Length == 1)
            {
                return(new BigInteger((long)Math.Sqrt(x.data[0])));
            }
            BigInteger z = new BigInteger();

            z.sign = 1;
            z.data = new byte[x.data.Length / 2 + 3];
            z.data = Adjust(BigArithmetic.Sqrt(z.data, z.data, z.data.Length, x.data, x.data.Length), x.data.Length);
            z.Shrink();
            BigInteger z1 = z + 1; // 平方根有可能比实际小 1。

            return((z1 * z1 <= x) ? z1 : z);
        }