예제 #1
0
        public static BigNumber operator +(BigNumber a, BigNumber b)
        {
            BigNumber r = new BigNumber(Math.Max(a.buffer.Length, b.buffer.Length));
            //r.negative = (a.negative && !b.negative) || (!a.negative && b.negative);

            for (int i = 0; i < Math.Max(a.buffer.Length, b.buffer.Length); i++)
            {
                r.buffer[i] += (byte)(a.gb(i) + b.gb(i));
                if (r.buffer[i] >= 100)
                {
                    r.buffer[i + 1] += (byte)(r.buffer[i] / 100); //TODO: OVERFLOW
                    r.buffer[i] = (byte)(r.buffer[i] % 100);
                }
            }

            return r;
        }
예제 #2
0
 public static BigNumber Parse(string t, int size)
 {
     if (string.IsNullOrEmpty(t))
         throw new ArgumentException("String to parse cannot be null or empty.", "t");
     BigNumber v = new BigNumber(size);
     int i = 0;
     if (t[i++] == '-')
         v.negative = true;
     else
         i--;
     while (i < t.Length)
     {
         v.buffer[(t.Length - i - 1) / 2] += (byte)(byte.Parse(new string(new char[] { t[i] })) * ((t.Length - i - 1) % 2 == 1 ? 10 : 1));
         i++;
     }
     return v;
 }
예제 #3
0
        static void Sqrt(BigNumber src, BigNumber dst, int places)
        {
            int  ii, nexp, tolerance, dplaces;
            bool bflag;

            if (src.signum <= 0)
            {
                if (src.signum == -1)
                {
                    throw new BigNumberException("'Sqrt',Invalid Argument");
                }
            }

            BigNumber last_x = new BigNumber();
            BigNumber guess  = new BigNumber();
            BigNumber tmpN   = new BigNumber();
            BigNumber tmp7   = new BigNumber();
            BigNumber tmp8   = new BigNumber();
            BigNumber tmp9   = new BigNumber();

            BigNumber.Copy(src, tmpN);

            nexp           = src.exponent / 2;
            tmpN.exponent -= 2 * nexp;

            BigNumber.SQrtGuess(tmpN, guess);

            tolerance = places + 4;
            dplaces   = places + 16;
            bflag     = false;

            BigNumber.Neg(BigNumber.Ten, last_x);

            ii = 0;

            while (true)
            {
                BigNumber.Mul(tmpN, guess, tmp9);
                BigNumber.Mul(tmp9, guess, tmp8);
                BigNumber.Round(tmp8, tmp7, dplaces);
                BigNumber.Sub(BigNumber.Three, tmp7, tmp9);
                BigNumber.Mul(tmp9, guess, tmp8);
                BigNumber.Mul(tmp8, BigNumber.BN_OneHalf, tmp9);

                if (bflag)
                {
                    break;
                }

                BigNumber.Round(tmp9, guess, dplaces);

                if (ii != 0)
                {
                    BigNumber.Sub(guess, last_x, tmp7);

                    if (tmp7.signum == 0)
                    {
                        break;
                    }

                    /*
                     *   if we are within a factor of 4 on the error term,
                     *   we will be accurate enough after the *next* iteration
                     *   is complete.  (note that the sign of the exponent on
                     *   the error term will be a negative number).
                     */

                    if ((-4 * tmp7.exponent) > tolerance)
                    {
                        bflag = true;
                    }
                }

                BigNumber.Copy(guess, last_x);
                ii++;
            }

            BigNumber.Mul(tmp9, tmpN, tmp8);
            BigNumber.Round(tmp8, dst, places);
            dst.exponent += nexp;
        }
예제 #4
0
        static private void IntPow(int places, BigNumber src, int mexp, BigNumber dst)
        {
            BigNumber A, B, C;
            int       nexp, ii, signflag, local_precision;

            if (mexp == 0)
            {
                BigNumber.Copy(BigNumber.One, dst);
                return;
            }
            else
            {
                if (mexp > 0)
                {
                    signflag = 0;
                    nexp     = mexp;
                }
                else
                {
                    signflag = 1;
                    nexp     = -mexp;
                }
            }

            if (src.signum == 0)
            {
                BigNumber.SetZero(dst);
                return;
            }

            A = new BigNumber();
            B = new BigNumber();
            C = new BigNumber();

            local_precision = places + 8;

            BigNumber.Copy(BigNumber.One, B);
            BigNumber.Copy(src, C);

            while (true)
            {
                ii   = nexp & 1;
                nexp = nexp >> 1;

                if (ii != 0)                       /* exponent -was- odd */
                {
                    BigNumber.Mul(B, C, A);
                    BigNumber.Round(A, B, local_precision);

                    if (nexp == 0)
                    {
                        break;
                    }
                }

                BigNumber.Mul(C, C, A);
                BigNumber.Round(A, C, local_precision);
            }

            if (signflag > 0)
            {
                BigNumber.Reziprocal(B, dst, places);
            }
            else
            {
                BigNumber.Round(B, dst, places);
            }
        }
예제 #5
0
        static void Log(BigNumber src, BigNumber dst, int places)
        {
            BigNumber tmp0, tmp1, tmp2;
            int       mexp, dplaces;

            if (src.signum <= 0)
            {
                throw new BigNumberException(" 'Log', Negative argument");
            }

            tmp0 = new BigNumber();
            tmp1 = new BigNumber();
            tmp2 = new BigNumber();

            dplaces = places + 8;

            mexp = src.exponent;

            if (mexp == 0 || mexp == 1)
            {
                BigNumber.Sub(src, BigNumber.One, tmp0);

                if (tmp0.signum == 0)    /* is input exactly 1 ?? */
                {                        /* if so, result is 0    */
                    BigNumber.SetZero(dst);
                    return;
                }

                if (tmp0.exponent <= -4)
                {
                    M_log_near_1(tmp0, dst, places);
                    return;
                }
            }

            /* make sure our log(10) is accurate enough for this calculation */
            /* (and log(2) which is called from M_log_basic_iteration) */

            BigNumber.CheckLogPlaces(dplaces + 25);

            if (Math.Abs(mexp) <= 3)
            {
                M_log_basic_iteration(src, dst, places);
            }
            else
            {
                /*
                 *  use log (x * y) = log(x) + log(y)
                 *
                 *  here we use y = exponent of our base 10 number.
                 *
                 *  let 'C' = log(10) = 2.3025850929940....
                 *
                 *  then log(x * y) = log(x) + ( C * base_10_exponent )
                 */

                BigNumber.Copy(src, tmp2);

                mexp          = tmp2.exponent - 2;
                tmp2.exponent = 2;

                M_log_basic_iteration(tmp2, tmp0, dplaces);

                BigNumber.SetFromLong(tmp1, (long)mexp);
                BigNumber.Mul(tmp1, BN_lc_log10, tmp2);
                BigNumber.Add(tmp2, tmp0, tmp1);

                BigNumber.Round(tmp1, dst, places);
            }
        }
예제 #6
0
        static private String ToIntString(BigNumber atm)
        {
            int ct, dl, numb, ii;

            ct = atm.exponent;
            dl = atm.dataLength;
            String result = String.Empty;

            byte numdiv = 0, numrem = 0;

            if (ct <= 0 || atm.signum == 0)
            {
                return("0");
            }

            if (ct > 112)
            {
                BigNumber.Expand(atm, ct + 32);
            }

            ii = 0;

            if (atm.signum == -1)
            {
                ii      = 1;
                result += "-";
            }

            if (ct > dl)
            {
                numb = (dl + 1) >> 1;
            }
            else
            {
                numb = (ct + 1) >> 1;
            }

            int ucp = 0;

            while (true)
            {
                Unpack(atm.mantissa[ucp++], ref numdiv, ref numrem);

                result += (char)('0' + numdiv);
                result += (char)('0' + numrem);

                if (--numb == 0)
                {
                    break;
                }
            }

            if (ct > dl)
            {
                for (int i = 0; i < (ct + 1 - dl); i++)
                {
                    result += '0';
                }
            }

            result = result.Substring(0, ct + ii);


            return(result);
        }
예제 #7
0
 static private int SignificantDigits(BigNumber atm)
 {
     return(atm.dataLength);
 }
예제 #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="ctmp"></param>
        /// <param name="count"></param>
        static private void Scale(BigNumber ctmp, int count)
        {
            int ii, numb, ct;

            ct = count;
            byte numdiv = 0, numdiv2 = 0, numrem = 0;

            ii = (ctmp.dataLength + ct + 1) >> 1;

            if (ii > ctmp.mantissa.Length)
            {
                BigNumber.Expand(ctmp, (ii + 32));
            }

            if ((ct & 1) != 0)          /* move odd number first */
            {
                ct--;

                ii = ((ctmp.dataLength + 1) >> 1) - 1;

                if ((ctmp.dataLength & 1) == 0)
                {
                    /*
                     *   original datalength is even:
                     *
                     *   uv  wx  yz   becomes  -->   0u  vw  xy  z0
                     */

                    numdiv = 0;

                    while (true)
                    {
                        Unpack(ctmp.mantissa[ii], ref numdiv2, ref numrem);

                        ctmp.mantissa[ii + 1] = (byte)(10 * numrem + numdiv);
                        numdiv = numdiv2;

                        if (ii == 0)
                        {
                            break;
                        }

                        ii--;
                    }

                    ctmp.mantissa[0] = numdiv2;
                }
                else
                {
                    /*
                     *   original datalength is odd:
                     *
                     *   uv  wx  y0   becomes  -->   0u  vw  xy
                     */

                    Unpack(ctmp.mantissa[ii], ref numdiv2, ref numrem);

                    if (ii == 0)
                    {
                        ctmp.mantissa[0] = numdiv2;
                    }
                    else
                    {
                        while (true)
                        {
                            Unpack(ctmp.mantissa[ii - 1], ref numdiv, ref numrem);

                            ctmp.mantissa[ii] = (byte)(10 * numrem + numdiv2);
                            numdiv2           = numdiv;

                            if (--ii == 0)
                            {
                                break;
                            }
                        }

                        ctmp.mantissa[0] = numdiv;
                    }
                }

                ctmp.exponent++;
                ctmp.dataLength++;
            }

            /* ct is even here */

            if (ct > 0)
            {
                numb = (ctmp.dataLength + 1) >> 1;
                ii   = ct >> 1;

                byte[] newData = new byte[ctmp.mantissa.Length];
                Array.Copy(ctmp.mantissa, 0, newData, ii, numb);

                for (int i = 0; i < ii; i++)
                {
                    newData[i] = 0;
                }

                ctmp.mantissa = newData;

                ctmp.dataLength += ct;
                ctmp.exponent   += ct;
            }
        }
예제 #9
0
        static private void Div(BigNumber aa, BigNumber bb, BigNumber rr, int places)
        {
            int   j, k, m, b0, nexp, indexr, icompare, iterations;
            sbyte sign;
            long  trial_numer;

            BigNumber M_div_worka = new BigNumber();
            BigNumber M_div_workb = new BigNumber();
            BigNumber M_div_tmp7  = new BigNumber();
            BigNumber M_div_tmp8  = new BigNumber();
            BigNumber M_div_tmp9  = new BigNumber();

            sign = (sbyte)(aa.signum * bb.signum);

            if (sign == 0)      /* one number is zero, result is zero */
            {
                if (bb.signum == 0)
                {
                    throw new BigNumberException("Division by Zero");
                }
                BigNumber.SetZero(rr);
                return;
            }

            if (bb.mantissa[0] >= 50)
            {
                BigNumber.Abs(M_div_worka, aa);
                BigNumber.Abs(M_div_workb, bb);
            }
            else       /* 'normal' step D1 */
            {
                k = 100 / (bb.mantissa[0] + 1);
                BigNumber.SetFromLong(M_div_tmp9, (long)k);

                BigNumber.Mul(M_div_tmp9, aa, M_div_worka);
                BigNumber.Mul(M_div_tmp9, bb, M_div_workb);

                M_div_worka.signum = 1;
                M_div_workb.signum = 1;
            }

            b0 = 100 * (int)M_div_workb.mantissa[0];

            if (M_div_workb.dataLength >= 3)
            {
                b0 += M_div_workb.mantissa[1];
            }

            nexp = M_div_worka.exponent - M_div_workb.exponent;

            if (nexp > 0)
            {
                iterations = nexp + places + 1;
            }
            else
            {
                iterations = places + 1;
            }

            k = (iterations + 1) >> 1;     /* required size of result, in bytes */

            if (k > rr.mantissa.Length)
            {
                BigNumber.Expand(rr, k + 32);
            }

            /* clear the exponent in the working copies */

            M_div_worka.exponent = 0;
            M_div_workb.exponent = 0;

            /* if numbers are equal, ratio == 1.00000... */

            if ((icompare = BigNumber.Compare(M_div_worka, M_div_workb)) == 0)
            {
                iterations     = 1;
                rr.mantissa[0] = 10;
                nexp++;
            }
            else                                  /* ratio not 1, do the real division */
            {
                if (icompare == 1)                /* numerator > denominator */
                {
                    nexp++;                       /* to adjust the final exponent */
                    M_div_worka.exponent += 1;    /* multiply numerator by 10 */
                }
                else                              /* numerator < denominator */
                {
                    M_div_worka.exponent += 2;    /* multiply numerator by 100 */
                }

                indexr = 0;
                m      = 0;

                while (true)
                {
                    /*
                     *  Knuth step D3. Only use the 3rd -> 6th digits if the number
                     *  actually has that many digits.
                     */

                    trial_numer = 10000L * (long)M_div_worka.mantissa[0];

                    if (M_div_worka.dataLength >= 5)
                    {
                        trial_numer += 100 * M_div_worka.mantissa[1] + M_div_worka.mantissa[2];
                    }
                    else
                    {
                        if (M_div_worka.dataLength >= 3)
                        {
                            trial_numer += 100 * M_div_worka.mantissa[1];
                        }
                    }

                    j = (int)(trial_numer / b0);

                    /*
                     *    Since the library 'normalizes' all the results, we need
                     *    to look at the exponent of the number to decide if we
                     *    have a lead in 0n or 00.
                     */

                    if ((k = 2 - M_div_worka.exponent) > 0)
                    {
                        while (true)
                        {
                            j /= 10;
                            if (--k == 0)
                            {
                                break;
                            }
                        }
                    }

                    if (j == 100)       /* qhat == base ??      */
                    {
                        j = 99;         /* if so, decrease by 1 */
                    }
                    BigNumber.SetFromLong(M_div_tmp8, (long)j);
                    BigNumber.Mul(M_div_tmp8, M_div_workb, M_div_tmp7);

                    /*
                     *    Compare our q-hat (j) against the desired number.
                     *    j is either correct, 1 too large, or 2 too large
                     *    per Theorem B on pg 272 of Art of Compter Programming,
                     *    Volume 2, 3rd Edition.
                     *
                     *    The above statement is only true if using the 2 leading
                     *    digits of the numerator and the leading digit of the
                     *    denominator. Since we are using the (3) leading digits
                     *    of the numerator and the (2) leading digits of the
                     *    denominator, we eliminate the case where our q-hat is
                     *    2 too large, (and q-hat being 1 too large is quite remote).
                     */

                    if (BigNumber.Compare(M_div_tmp7, M_div_worka) == 1)
                    {
                        j--;
                        BigNumber.Sub(M_div_tmp7, M_div_workb, M_div_tmp8);
                        BigNumber.Copy(M_div_tmp8, M_div_tmp7);
                    }

                    /*
                     *  Since we know q-hat is correct, step D6 is unnecessary.
                     *
                     *  Store q-hat, step D5. Since D6 is unnecessary, we can
                     *  do D5 before D4 and decide if we are done.
                     */

                    rr.mantissa[indexr++] = (byte)j;    /* j == 'qhat' */
                    m += 2;

                    if (m >= iterations)
                    {
                        break;
                    }

                    /* step D4 */

                    BigNumber.Sub(M_div_worka, M_div_tmp7, M_div_tmp9);

                    /*
                     *  if the subtraction yields zero, the division is exact
                     *  and we are done early.
                     */

                    if (M_div_tmp9.signum == 0)
                    {
                        iterations = m;
                        break;
                    }

                    /* multiply by 100 and re-save */
                    M_div_tmp9.exponent += 2;
                    BigNumber.Copy(M_div_tmp9, M_div_worka);
                }
            }

            rr.signum     = sign;
            rr.exponent   = nexp;
            rr.dataLength = iterations;

            BigNumber.Normalize(rr);
        }
예제 #10
0
        /// <summary>
        /// compare 2 numbers
        /// </summary>
        /// <param name="ltmp"></param>
        /// <param name="rtmp"></param>
        /// <returns></returns>
        static public int Compare(BigNumber ltmp, BigNumber rtmp)
        {
            int llen, rlen, lsign, rsign, i, j, lexp, rexp;

            llen = ltmp.dataLength;
            rlen = rtmp.dataLength;

            lsign = ltmp.signum;
            rsign = rtmp.signum;

            lexp = ltmp.exponent;
            rexp = rtmp.exponent;

            if (rsign == 0)
            {
                return(lsign);
            }

            if (lsign == 0)
            {
                return(-rsign);
            }

            if (lsign == -rsign)
            {
                return(lsign);
            }

            if (lexp > rexp)
            {
                goto E1;
            }

            if (lexp < rexp)
            {
                goto E2;
            }

            if (llen < rlen)
            {
                j = (llen + 1) >> 1;
            }
            else
            {
                j = (rlen + 1) >> 1;
            }

            for (i = 0; i < j; i++)
            {
                if (ltmp.mantissa[i] > rtmp.mantissa[i])
                {
                    goto E1;
                }

                if (ltmp.mantissa[i] < rtmp.mantissa[i])
                {
                    goto E2;
                }
            }

            if (llen == rlen)
            {
                return(0);
            }
            else
            {
                if (llen > rlen)
                {
                    goto E1;
                }
                else
                {
                    goto E2;
                }
            }

E1:

            if (lsign == 1)
            {
                return(1);
            }
            else
            {
                return(-1);
            }

E2:

            if (lsign == 1)
            {
                return(-1);
            }
            else
            {
                return(1);
            }
        }
예제 #11
0
 public BigNumber(BigNumber anotherBigNumber)
 {
     length = anotherBigNumber.length;
     sign   = anotherBigNumber.sign;
     data   = anotherBigNumber.data;
 }
예제 #12
0
 public static bool IsZero(BigNumber number)
 {
     return(number.length == 0 || (number.length == 1 && number.data[0] == 0));
 }
 static public void Reziprocal(BigNumber src, BigNumber dst, int places)
 {
     BigNumber.Div(BigNumber.One, src, dst, places);
 }
예제 #14
0
        static private String ToExpString(BigNumber atm, int digits)
        {
            int  i, index, first, max_i, num_digits, dec_places;
            byte numdiv = 0, numrem = 0;

            BigNumber ctmp = new BigNumber();
            String    res  = "";

            dec_places = digits;

            if (dec_places < 0)
            {
                BigNumber.Copy(atm, ctmp);
            }
            else
            {
                BigNumber.Round(atm, ctmp, dec_places);
            }

            if (ctmp.signum == 0)
            {
                if (dec_places < 0)
                {
                    res = "0.0E+0";
                }
                else
                {
                    res = "0";

                    if (dec_places > 0)
                    {
                        res += ".";
                    }

                    for (i = 0; i < dec_places; i++)
                    {
                        res += "0";
                    }

                    res += "E+0";
                }
                return(res);
            }

            max_i = (ctmp.dataLength + 1) >> 1;

            if (dec_places < 0)
            {
                num_digits = ctmp.dataLength;
            }
            else
            {
                num_digits = dec_places + 1;
            }
            if (ctmp.signum == -1)
            {
                res += '-';
            }

            first = 1;

            i     = 0;
            index = 0;

            while (true)
            {
                if (index >= max_i)
                {
                    numdiv = 0;
                    numrem = 0;
                }
                else
                {
                    Unpack(ctmp.mantissa[index], ref numdiv, ref numrem);
                }

                index++;

                res += (char)('0' + numdiv);

                if (++i == num_digits)
                {
                    break;
                }

                if (first != 0)
                {
                    first = 0;
                    res  += '.';
                }

                res += (char)('0' + numrem);

                if (++i == num_digits)
                {
                    break;
                }
            }

            i = ctmp.exponent - 1;

            if (i >= 0)
            {
                res += "E+" + i;
            }
            else if (i < 0)
            {
                res += "E" + i;
            }


            return(res);
        }
예제 #15
0
        static public void Div(BigNumber aa, BigNumber bb, BigNumber rr)
        {
            int places = BigNumber.MaxDigits(aa, bb);

            BigNumber.Div(aa, bb, rr, places);
        }
예제 #16
0
        public static void DoTest()
        {
            BigNumber A = 0, B = 0, C = 0;
            BigNumber PI = new BigNumber();

            // assignment by string
            A = "12345";
            Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")");

            // assignment from hexadecimal string
            A = "0xff";
            Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")");

            A = "0x1ff";
            Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")");

            A = "0x123456789";
            Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")");

            A = "0xFeDcBafedcba";
            Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")");

            // assignment from binary string
            A = "%10001000";
            Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")");

            A = "%11011011100111000111000111100011010101010101";
            Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")");

            // assignment by double
            A = 123.45;
            B = 0.12345;
            Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")");

            // assignment by string in exponential form x = a*10^y. 10E3 = 10*10^^3 = 10000
            A = "10E3";     // 10E3 = 10*10^3 = 10000
            B = "1E4";      // 1E4  =  1*10^4 = 10000
            C = 10000;
            Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")");
            Console.WriteLine("10000 = " + A.ToFullString() + " = " + B.ToFullString() + " = " + C.ToFullString());

            A = 1; B = 2; C = 0;
            C = A + B;
            Console.WriteLine("the result of " + A.ToFullString() + "+" + B.ToFullString() + "=" + C.ToFullString());
            // addition of BigNumber + double
            C = A + 3.2;
            // addition of double + BigNumber
            C = 3.1 + B;
            A = "5.141592"; B = "2.91827";
            C = A - B;
            Console.WriteLine("the result of " + A.ToFullString() + "-" + B.ToFullString() + "=" + C.ToFullString());

            C = A * B;
            Console.WriteLine("the result of " + A.ToFullString() + "*" + B.ToFullString() + "=" + C.ToFullString());
            A = 5.0; B = 3.0;
            C = A * B;
            Console.WriteLine("the result of " + A.ToFullString() + "*" + B.ToFullString() + "=" + C.ToFullString());

            A = 4; B = 0.5;
            C = A.Pow(B);
            Console.WriteLine("the result of " + A.ToFullString() + " pow " + B.ToFullString() + "=" + C.ToFullString());

            A = 0.5; B = "5E-1";
            C = A.Pow(B, 16);
            Console.WriteLine("the result of " + A.ToFullString() + " pow " + B.ToFullString() + "=" + C.ToFullString());

            A = "1e3"; // "10E2"; //   "1E3 = 1000";
            C = A.Log10();
            Console.WriteLine("the result of " + A.ToFullString() + " Log10 =" + C.ToFullString());

            A = "10E3"; B = "1E4"; C = 10000;

            A = BigNumber.BN_E;
            C = A.Log();
            Console.WriteLine("the result of " + A.ToString() + " Log =" + C.ToFullString());

            A = 3.0;
            C = A.Rez();
            Console.WriteLine("the result of " + A.ToString() + " Rez =" + C.ToFullString());

            int NumPlaces = 4;

            A = 1.53456;
            C = A.Round(NumPlaces);
            Console.WriteLine("the result of " + A.ToString() + " Round(" + NumPlaces + ") =" + C.ToFullString());

            NumPlaces = 2;
            C         = A.Round(NumPlaces);
            Console.WriteLine("the result of " + A.ToString() + " Round(" + NumPlaces + ") =" + C.ToFullString());

            NumPlaces = 0;
            C         = A.Round(NumPlaces);
            Console.WriteLine("the result of " + A.ToString() + " Round(" + NumPlaces + ") =" + C.ToFullString());

            NumPlaces = 16;
            A         = 2.0;
            C         = A.Sqrt(NumPlaces);
            Console.WriteLine("the result of " + A.ToString() + " Sqrt(" + NumPlaces + ") =" + C.ToFullString());

            A = 1.0; B = 0;
            try
            {
                C = A / B;
            }
            catch (BigNumberException ex)
            {
                Console.WriteLine("Exception in operation: " + ex.Message);
            }

            A = 1.0;
            for (int i = 1; i <= 1000; i++)
            {
                A = A * i;
            }

            Console.WriteLine("the result of 1000!=" + A.ToFullString());
            A = A.Round(numDefaultPlaces);
            Console.WriteLine("the result of 1000!=" + A.ToString());

            DateTime before = DateTime.Now;

            NumPlaces = 5000;
            CalculatePiAGM(PI, NumPlaces);

            TimeSpan ts = DateTime.Now - before;

            Console.WriteLine("time for " + NumPlaces + " digits of PI: " + ts.TotalMilliseconds + "[ms]");
            Console.WriteLine(PI.ToFullString());

            Console.WriteLine("Press 'x' key to quit test");
            //while (true)
            //{
            //    ConsoleKeyInfo i = Console.ReadKey();
            //    if (i.KeyChar == 'x') break;
            //}
        }
예제 #17
0
        static private void Mul(BigNumber aa, BigNumber bb, BigNumber rr)
        {
            int   ai, itmp, nexp, ii, jj, indexa, indexb, index0, numdigits;
            sbyte sign;

            sign = (sbyte)(aa.signum * bb.signum);
            nexp = aa.exponent + bb.exponent;

            if (sign == 0)
            {
                BigNumber.SetZero(rr);
                return;
            }

            numdigits = aa.dataLength + bb.dataLength;
            indexa    = (aa.dataLength + 1) >> 1;
            indexb    = (bb.dataLength + 1) >> 1;

            if (indexa >= 48 && indexb >= 48)
            {
                BigNumber.FastMul(aa, bb, rr);
                return;
            }

            ii = (numdigits + 1) >> 1;

            if (ii >= rr.mantissa.Length)
            {
                BigNumber.Expand(rr, ii + 32);
            }

            index0 = indexa + indexb;
            for (int i = 0; i < index0; i++)
            {
                rr.mantissa[i] = 0;
            }

            ii = indexa;

            while (true)
            {
                index0--;
                int crp = index0;
                jj = indexb;
                ai = (int)aa.mantissa[--ii];

                while (true)
                {
                    itmp = ai * bb.mantissa[--jj];

                    rr.mantissa[crp - 1] += s_MsbLookupMult[itmp];
                    rr.mantissa[crp]     += s_LsbLookupMult[itmp];

                    if (rr.mantissa[crp] >= 100)
                    {
                        rr.mantissa[crp]     -= 100;
                        rr.mantissa[crp - 1] += 1;
                    }

                    crp--;

                    if (rr.mantissa[crp] >= 100)
                    {
                        rr.mantissa[crp]     -= 100;
                        rr.mantissa[crp - 1] += 1;
                    }

                    if (jj == 0)
                    {
                        break;
                    }
                }

                if (ii == 0)
                {
                    break;
                }
            }

            rr.signum     = sign;
            rr.exponent   = nexp;
            rr.dataLength = numdigits;

            BigNumber.Normalize(rr);
        }
예제 #18
0
        static private void CalculatePiMachin(BigNumber outv, int places)
        {
            BigNumber curanswer;
            BigNumber lastanswer;

            BigNumber term5;
            BigNumber term239;
            BigNumber term5m;
            BigNumber term239m;
            BigNumber diff;
            BigNumber lim;

            int  n5;
            int  n239;
            bool b5termdone   = false;
            bool b239termdone = false;

            lim = 1;

            lim /= (Math.Pow(10, places));

            n5   = 0;
            n239 = 0;

            term5  = 16;
            term5 /= 5;

            term239  = 4;
            term239 /= 239;

            curanswer  = 0;
            lastanswer = 0;

            while (b5termdone == false && b239termdone == false)
            {
                lastanswer = curanswer;

                term5m  = term5;
                term5m /= n5 * 2 + 1;

                term239m  = term239;
                term239m /= n239 * 2 + 1;

                if (n5 % 2 == 0)
                {
                    curanswer += term5m;   /* n5 is even */
                }
                else
                {
                    curanswer -= term5m;   /* n5 is odd */
                }

                if (n239 % 2 == 0)
                {
                    curanswer -= term239m;   /* n239 is even */
                }
                else
                {
                    curanswer += term239m;   /* n239 is odd */
                }

                term5 /= 25;  // 5*5
                n5++;

                term239 /= 57121;  //  239 * 239;
                n239++;

                diff = lastanswer - curanswer;
                BigNumber.Abs(diff, diff);

                if (diff < lim)
                {
                    break;
                }
            }

            BigNumber.Round(curanswer, outv, places);
        }
예제 #19
0
        static private void SetFromString(BigNumber atm, String value, bool isStrainghtDigitsOnly = false)
        {
            SetZero(atm);

            int   p        = 0;
            sbyte sign     = 1;
            int   exponent = 0;

            if (isStrainghtDigitsOnly == false)
            {
                value = value.Trim();               // trim whitespace
                value = value.ToLower();            // convert to lower
                //value = UtilityHandler.ToLowerFast(value);

                int cp = value.IndexOf("0x");       // hexadezimalnumber
                if (cp >= 0)
                {
                    value = value.Substring(cp + 2, value.Length - (cp + 2));
                    BigNumber.SetFromHexString(atm, value);
                    return;
                }

                cp = value.IndexOf("%");       // binary format number
                if (cp >= 0)
                {
                    value = value.Substring(cp + 1, value.Length - (cp + 1));
                    BigNumber.SetFromBinaryString(atm, value);
                    return;
                }

                cp = value.IndexOf("e");
                if (cp > 0) // e cannot be leading
                {
                    String ex = value.Substring(cp + 1, value.Length - (cp + 1));
                    exponent = Convert.ToInt32(ex);
                    value    = value.Substring(0, cp);
                }
            }



            if (value.Contains("+"))
            {
                value = value.Replace("+", ""); // remove optional '+' character
            }
            else if (value.Contains("-"))
            {
                sign  = -1;
                value = value.Replace("-", "");
            }

            value = value.Replace(",", ".");

            int j = value.IndexOf(".");

            if (j == -1)
            {
                value = value + '.';
                j     = value.IndexOf(".");
            }

            if (j > 0)
            {
                exponent += j;
                value     = value.Replace(".", "");
            }


            int i = value.Length;

            atm.dataLength = i;

            if ((i % 2) != 0)
            {
                value = value + '0';
            }

            j = value.Length >> 1;

            if (value.Length > atm.mantissa.Length)
            {
                BigNumber.Expand(atm, atm.dataLength + 28);
            }


            byte ch = 0;

            int zflag = 1;

            for (i = 0, p = 0; i < j; i++)
            {
                ch = (byte)(value[p++] - '0');

                if ((ch = (byte)((byte)(10 * ch) + (byte)(value[p++] - '0'))) != 0)
                {
                    zflag = 0;
                }

                if (((int)ch & 0xFF) >= 100)
                {
                    // Error!
                    SetZero(atm);
                    return;
                }

                atm.mantissa[i]     = ch;
                atm.mantissa[i + 1] = 0;
            }

            atm.exponent = exponent;
            atm.signum   = sign;

            if (zflag != 0)
            {
                atm.exponent    = 0;
                atm.signum      = 0;
                atm.dataLength  = 1;
                atm.mantissa[0] = 0;
            }
            else
            {
                Normalize(atm);
            }
        }
예제 #20
0
        //
        //                  1          2          3                    k
        //        pi = 2 + --- * (2 + --- * (2 + --- * (2 + ...  (2 + ---- * (2 + ... ))...)))
        //                  3          5          7                   2k+1
        // Calculation of pi to 32372 decimal digits */
        // Size of program: 152 characters */
        // After Dik T. Winter, CWI Amsterdam */
        //
        //  unsigned a=1e4,b,c=113316,d,e,f[113316],g,h,i;
        //  main(){for(;b=c,c-=14;i=printf("%04d",e+d/a),e=d%a)
        //  while(g=--b*2)d=h*b+a*(i?f[b]:a/5),h=d/--g,f[b]=d-g*h;}
        //
        //  unsigned a=1e4,b,c=113316,d,e,f[113316],g,h,i;
        //
        //  main()
        //  {
        //      for(;b=c,c-=14;i=printf("%04d",e+d/a),e=d%a)
        //      {
        //          while(g=--b*2)
        //          {
        //              d   = h*b+a*(i?f[b]:a/5);
        //              h   = d/--g;
        //              f[b]= d-g*h;
        //          }
        //       }
        //  }

        static private void CalculatePiSpigot(BigNumber outv, int places)
        {
        }
예제 #21
0
        /// <summary>
        /// normalize number
        /// </summary>
        /// <param name="atm"></param>
        static private void Normalize(BigNumber atm)
        {
            if (atm.signum == 0)
            {
                return;
            }
            int  ucp = 0;
            int  i;
            int  index;
            int  datalength = atm.dataLength;
            int  exponent = atm.exponent;
            byte numdiv = 0, numrem = 0, numrem2 = 0;

            BigNumber.Pad(atm, datalength + 3);

            // remove leading zeroes
            while (true)
            {
                // extract first 2 nibbles
                Unpack(atm.mantissa[0], ref numdiv, ref numrem);

                // if first digit is greater 1 we are done
                if (numdiv >= 1)
                {
                    break;
                }

                // otherwise we have leading zeroes
                index = (datalength + 1) >> 1;

                if (numrem == 0)    // both nibbles are 0
                {
                    i   = 0;
                    ucp = 0;

                    while (true)
                    {
                        if (atm.mantissa[ucp] != 0)
                        {
                            break;
                        }
                        ucp++;
                        i++;
                    }

                    byte[] copy = new byte[atm.mantissa.Length];
                    Array.Copy(atm.mantissa, ucp, copy, 0, (index + 1 - i));
                    atm.mantissa = copy;

                    datalength -= 2 * i;
                    exponent   -= 2 * i;
                }
                else
                {
                    for (i = 0; i < index; i++)
                    {
                        Unpack(atm.mantissa[i + 1], ref numdiv, ref numrem2);
                        atm.mantissa[i] = (byte)(10 * numrem + numdiv);
                        numrem          = numrem2;
                    }

                    datalength--;
                    exponent--;
                }
            }

            // remove trailing zeroes
            while (true)
            {
                index = ((datalength + 1) >> 1) - 1;

                if ((datalength & 1) == 0)   /* back-up full bytes at a time if the */
                {                            /* current length is an even number    */
                    ucp = index;
                    if (atm.mantissa[ucp] == 0)
                    {
                        while (true)
                        {
                            datalength -= 2;
                            index--;
                            ucp--;

                            if (atm.mantissa[ucp] != 0)
                            {
                                break;
                            }
                        }
                    }
                }

                Unpack(atm.mantissa[index], ref numdiv, ref numrem);

                if (numrem != 0)                /* last digit non-zero, all done */
                {
                    break;
                }

                if ((datalength & 1) != 0)   /* if odd, then first char must be non-zero */
                {
                    if (numdiv != 0)
                    {
                        break;
                    }
                }

                if (datalength == 1)
                {
                    atm.signum = 0;
                    exponent   = 0;
                    break;
                }

                datalength--;
            }

            atm.dataLength = datalength;
            atm.exponent   = exponent;
        }
예제 #22
0
        /****************************************************************************/

        /*
         *	define a notation for a function 'R' :
         *
         *
         *
         *                                    1
         *      R (a0, b0)  =  ------------------------------
         *
         *                          ----
         *                           \
         *                            \     n-1      2    2
         *                      1  -   |   2    *  (a  - b )
         *                            /              n    n
         *                           /
         *                          ----
         *                         n >= 0
         *
         *
         *      where a, b are the classic AGM iteration :
         *
         *
         *      a    =  0.5 * (a  + b )
         *       n+1            n    n
         *
         *
         *      b    =  sqrt(a  * b )
         *       n+1          n    n
         *
         *
         *
         *      define a variable 'c' for more efficient computation :
         *
         *                                      2     2     2
         *      c    =  0.5 * (a  - b )    ,   c  =  a  -  b
         *       n+1            n    n          n     n     n
         *
         */

        /****************************************************************************/
        static void     LogAGMRFunc(BigNumber aa, BigNumber bb, BigNumber rr, int places)
        {
            BigNumber tmp1, tmp2, tmp3, tmp4, tmpC2, sum, pow_2, tmpA0, tmpB0;
            int       tolerance, dplaces;

            tmpA0 = new BigNumber();
            tmpB0 = new BigNumber();
            tmpC2 = new BigNumber();
            tmp1  = new BigNumber();
            tmp2  = new BigNumber();
            tmp3  = new BigNumber();
            tmp4  = new BigNumber();
            sum   = new BigNumber();
            pow_2 = new BigNumber();

            tolerance = places + 8;
            dplaces   = places + 16;

            BigNumber.Copy(aa, tmpA0);
            BigNumber.Copy(bb, tmpB0);
            BigNumber.Copy(BigNumber.BN_OneHalf, pow_2);

            BigNumber.Mul(aa, aa, tmp1);                    /* 0.5 * [ a ^ 2 - b ^ 2 ] */
            BigNumber.Mul(bb, bb, tmp2);
            BigNumber.Sub(tmp1, tmp2, tmp3);
            BigNumber.Mul(BigNumber.BN_OneHalf, tmp3, sum);

            while (true)
            {
                BigNumber.Sub(tmpA0, tmpB0, tmp1);               /* C n+1 = 0.5 * [ An - Bn ] */
                BigNumber.Mul(BigNumber.BN_OneHalf, tmp1, tmp4); /* C n+1 */
                BigNumber.Mul(tmp4, tmp4, tmpC2);                /* C n+1 ^ 2 */

                /* do the AGM */

                BigNumber.Add(tmpA0, tmpB0, tmp1);
                BigNumber.Mul(BigNumber.BN_OneHalf, tmp1, tmp3);

                BigNumber.Mul(tmpA0, tmpB0, tmp2);
                BigNumber.Sqrt(tmp2, tmpB0, dplaces);

                BigNumber.Round(tmp3, tmpA0, dplaces);

                /* end AGM */

                BigNumber.Mul(BigNumber.Two, pow_2, tmp2);
                BigNumber.Copy(tmp2, pow_2);

                BigNumber.Mul(tmpC2, pow_2, tmp1);
                BigNumber.Add(sum, tmp1, tmp3);

                if ((tmp1.signum == 0) || ((-2 * tmp1.exponent) > tolerance))
                {
                    break;
                }

                BigNumber.Round(tmp3, sum, dplaces);
            }

            BigNumber.Sub(BigNumber.One, tmp3, tmp4);
            BigNumber.Reziprocal(tmp4, rr, places);
        }
예제 #23
0
 static private int Digits(BigNumber atm)
 {
     return(atm.dataLength < sMinPrecision ? sMinPrecision : atm.dataLength);
 }
예제 #24
0
        static private String ToFullString(BigNumber atm)
        {
            if (atm == 0)
            {
                return("0");
            }
            StringBuilder sb = new StringBuilder();

            sb.Append("");
            String res = "";
            byte   numdiv = 0, numrem = 0;

            int max_i = (atm.dataLength + 1) >> 1;
            int exp   = atm.exponent;

            for (int i = 0; i < max_i; i++)
            {
                BigNumber.Unpack(atm.mantissa[i], ref numdiv, ref numrem);
                //res += (char)('0' + numdiv);
                //res += (char)('0' + numrem);
                sb.Append((char)('0' + numdiv));
                sb.Append((char)('0' + numrem));
            }
            res = sb.ToString().Substring(0, atm.dataLength);
            sb.Clear();
            sb.Append(res);
            if (exp > 0)
            {
                for (int i = res.Length; i < exp; i++)
                {
                    //res += "0";
                    sb.Append("0");
                }

                if (exp < res.Length)
                {
                    //res = res.Insert(exp , ".");
                    sb.Insert(exp, ".");
                }
            }
            else if (exp <= 0)
            {
                while (exp++ <= 0)
                {
                    //res = "0" + res;
                    sb.Insert(0, "0");
                }
                res = sb.ToString();

                if (exp <= res.Length)
                {
                    //res = res.Insert(1, ".");
                    sb.Insert(1, ".");
                }
            }

            if (atm.signum < 0)   /*res = res.Insert(0, "-");*/
            {
                sb.Insert(0, "-");
            }
            res = sb.ToString();
            return(res);
        }