Пример #1
0
        public BigNumber Abs()
        {
            BigNumber res = 0;

            BigNumber.Abs(res, this);
            return(res);
        }
Пример #2
0
        static public void Sub(BigNumber src, BigNumber dst, BigNumber result)
        {
            int       itmp, j, ChangeOrderFlag, icompare, aexp, bexp, borrow, adigits, bdigits;
            sbyte     sign;
            BigNumber A = 0, B = 0;

            if (dst.signum == 0)
            {
                BigNumber.Copy(src, result);
                return;
            }

            if (src.signum == 0)
            {
                BigNumber.Copy(dst.Neg(), result);
                return;
            }

            if (src.signum == 1 && dst.signum == -1)
            {
                dst.signum = 1;
                Add(src, dst, result);
                dst.signum = -1;
                return;
            }

            if (src.signum == -1 && dst.signum == 1)
            {
                dst.signum = -1;
                Add(src, dst, result);
                dst.signum = 1;
                return;
            }

            BigNumber.Abs(A, src);
            BigNumber.Abs(B, dst);

            if ((icompare = Compare(A, B)) == 0)
            {
                SetZero(result);
                return;
            }

            if (icompare == 1)  /*  |a| > |b|  (do A-B)  */
            {
                ChangeOrderFlag = 1;
                sign            = src.signum;
            }
            else                /*  |b| > |a|  (do B-A)  */
            {
                ChangeOrderFlag = 0;
                sign            = (sbyte)-(src.signum);
            }

            aexp = A.exponent;
            bexp = B.exponent;

            if (aexp > bexp)
            {
                Scale(B, (aexp - bexp));
            }
            if (aexp < bexp)
            {
                Scale(A, (bexp - aexp));
            }

            adigits = A.dataLength;
            bdigits = B.dataLength;

            if (adigits > bdigits)
            {
                Pad(B, adigits);
            }

            if (adigits < bdigits)
            {
                Pad(A, bdigits);
            }

            if (ChangeOrderFlag == 1)            // |a| > |b|  (do A-B)
            {
                Copy(A, result);

                j = (result.dataLength + 1) >> 1;

                borrow = 0;

                while (true)
                {
                    j--;
                    itmp = ((int)result.mantissa[j] - ((int)B.mantissa[j] + borrow));

                    if (itmp >= 0)
                    {
                        result.mantissa[j] = (byte)itmp;
                        borrow             = 0;
                    }
                    else
                    {
                        result.mantissa[j] = (byte)(100 + itmp);
                        borrow             = 1;
                    }

                    if (j == 0)
                    {
                        break;
                    }
                }
            }
            else                // |b| > |a|  (do B-A) instead
            {
                Copy(B, result);

                j      = (result.dataLength + 1) >> 1;
                borrow = 0;

                while (true)
                {
                    j--;
                    itmp = (int)result.mantissa[j] - ((int)A.mantissa[j] + borrow);

                    if (itmp >= 0)
                    {
                        result.mantissa[j] = (byte)itmp;
                        borrow             = 0;
                    }
                    else
                    {
                        result.mantissa[j] = (byte)(100 + itmp);
                        borrow             = 1;
                    }

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

            result.signum = sign;

            BigNumber.Normalize(result);
        }
Пример #3
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);
        }
        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);
        }