Exemplo n.º 1
0
        /**
         * Returns a new {@code BigDecimal} whose value is {@code this *
         * multiplicand}. The result is rounded according to the passed context
         * {@code mc}.
         *
         * @param multiplicand
         *            value to be multiplied with {@code this}.
         * @param mc
         *            rounding mode and precision for the result of this operation.
         * @return {@code this * multiplicand}.
         * @throws NullPointerException
         *             if {@code multiplicand == null} or {@code mc == null}.
         */

        public static BigDecimal Multiply(BigDecimal value, BigDecimal multiplicand, MathContext mc)
        {
            BigDecimal result = Multiply(value, multiplicand);

            result.InplaceRound(mc);
            return(result);
        }
Exemplo n.º 2
0
        /**
         * Returns a new {@code BigDecimal} whose value is {@code this % divisor}.
         * <p>
         * The remainder is defined as {@code this -
         * this.divideToIntegralValue(divisor) * divisor}.
         * <p>
         * The specified rounding mode {@code mc} is used for the division only.
         *
         * @param divisor
         *            value by which {@code this} is divided.
         * @param mc
         *            rounding mode and precision to be used.
         * @return {@code this % divisor}.
         * @throws NullPointerException
         *             if {@code divisor == null}.
         * @throws ArithmeticException
         *             if {@code divisor == 0}.
         * @throws ArithmeticException
         *             if {@code mc.getPrecision() > 0} and the result of {@code
         *             this.divideToIntegralValue(divisor, mc)} requires more digits
         *             to be represented.
         */
        public static BigDecimal Remainder(BigDecimal a, BigDecimal b, MathContext context)
        {
            BigDecimal remainder;

            DivideAndRemainder(a, b, context, out remainder);
            return(remainder);
        }
Exemplo n.º 3
0
 /**
  * Returns a {@code BigDecimal} array which contains the integral part of
  * {@code this / divisor} at index 0 and the remainder {@code this %
  * divisor} at index 1. The quotient is rounded down towards zero to the
  * next integer. The rounding mode passed with the parameter {@code mc} is
  * not considered. But if the precision of {@code mc > 0} and the integral
  * part requires more digits, then an {@code ArithmeticException} is thrown.
  *
  * @param divisor
  *            value by which {@code this} is divided.
  * @param mc
  *            math context which determines the maximal precision of the
  *            result.
  * @return {@code [this.divideToIntegralValue(divisor),
  *         this.remainder(divisor)]}.
  * @throws NullPointerException
  *             if {@code divisor == null}.
  * @throws ArithmeticException
  *             if {@code divisor == 0}.
  * @see #divideToIntegralValue
  * @see #remainder
  */
 public static BigDecimal DivideAndRemainder(BigDecimal a,
                                             BigDecimal b,
                                             MathContext context,
                                             out BigDecimal remainder)
 {
     return(BigDecimalMath.DivideAndRemainder(a, b, context, out remainder));
 }
Exemplo n.º 4
0
        public BigComplex Inverse(MathContext mc)
        {
            BigDecimal hyp = Norm();

            /* 1/(x+iy)= (x-iy)/(x^2+y^2 */
            return(new BigComplex(Real.Divide(hyp, mc), Imaginary.Divide(hyp, mc).Negate()));
        }
Exemplo n.º 5
0
        /**
         * Returns a new {@code BigDecimal} whose value is {@code this}, rounded
         * according to the passed context {@code mc}.
         * <p>
         * If {@code mc.precision = 0}, then no rounding is performed.
         * <p>
         * If {@code mc.precision > 0} and {@code mc.roundingMode == UNNECESSARY},
         * then an {@code ArithmeticException} is thrown if the result cannot be
         * represented exactly within the given precision.
         *
         * @param mc
         *            rounding mode and precision for the result of this operation.
         * @return {@code this} rounded according to the passed context.
         * @throws ArithmeticException
         *             if {@code mc.precision > 0} and {@code mc.roundingMode ==
         *             UNNECESSARY} and this cannot be represented within the given
         *             precision.
         */
        public static BigDecimal Round(BigDecimal number, MathContext mc)
        {
            var thisBD = new BigDecimal(number.UnscaledValue, number.Scale);

            thisBD.InplaceRound(mc);
            return(thisBD);
        }
Exemplo n.º 6
0
        public BigComplex Sqrt(MathContext mc)
        {
            BigDecimal half = new BigDecimal(2);

            /* compute l=sqrt(re^2+im^2), then u=sqrt((l+re)/2)
             * and v= +- sqrt((l-re)/2 as the new real and imaginary parts.
             */
            BigDecimal l = Abs(mc);

            if (l.CompareTo(BigDecimal.Zero) == 0)
            {
                return(new BigComplex(BigMath.ScalePrecision(BigDecimal.Zero, mc),
                                      BigMath.ScalePrecision(BigDecimal.Zero, mc)));
            }
            BigDecimal u = BigMath.Sqrt(l.Add(Real).Divide(half, mc), mc);
            BigDecimal v = BigMath.Sqrt(l.Subtract(Real).Divide(half, mc), mc);

            if (Imaginary.CompareTo(BigDecimal.Zero) >= 0)
            {
                return(new BigComplex(u, v));
            }
            else
            {
                return(new BigComplex(u, v.Negate()));
            }
        }
Exemplo n.º 7
0
        public BigComplex Multiply(BigComplex oth, MathContext mc)
        {
            BigDecimal a = Real.Add(Imaginary).Multiply(oth.Real);
            BigDecimal b = oth.Real.Add(oth.Imaginary).Multiply(Imaginary);
            BigDecimal c = oth.Imaginary.Subtract(oth.Real).Multiply(Real);
            BigDecimal x = a.Subtract(b, mc);
            BigDecimal y = a.Add(c, mc);

            return(new BigComplex(x, y));
        }
        public static BigDecimal Add(BigDecimal value, BigDecimal augend, MathContext mc)
        {
            BigDecimal larger;             // operand with the largest unscaled value
            BigDecimal smaller;            // operand with the smallest unscaled value
            BigInteger tempBi;
            long       diffScale = (long)value.Scale - augend.Scale;

            // Some operand is zero or the precision is infinity
            if ((augend.IsZero) || (value.IsZero) || (mc.Precision == 0))
            {
                return(BigMath.Round(Add(value, augend), mc));
            }
            // Cases where there is room for optimizations
            if (value.AproxPrecision() < diffScale - 1)
            {
                larger  = augend;
                smaller = value;
            }
            else if (augend.AproxPrecision() < -diffScale - 1)
            {
                larger  = value;
                smaller = augend;
            }
            else
            {
                // No optimization is done
                return(BigMath.Round(Add(value, augend), mc));
            }
            if (mc.Precision >= larger.AproxPrecision())
            {
                // No optimization is done
                return(BigMath.Round(Add(value, augend), mc));
            }

            // Cases where it's unnecessary to add two numbers with very different scales
            var largerSignum = larger.Sign;

            if (largerSignum == smaller.Sign)
            {
                tempBi = Multiplication.MultiplyByPositiveInt(larger.UnscaledValue, 10) +
                         BigInteger.FromInt64(largerSignum);
            }
            else
            {
                tempBi = larger.UnscaledValue - BigInteger.FromInt64(largerSignum);
                tempBi = Multiplication.MultiplyByPositiveInt(tempBi, 10) +
                         BigInteger.FromInt64(largerSignum * 9);
            }
            // Rounding the improved adding
            larger = new BigDecimal(tempBi, larger.Scale + 1);
            return(BigMath.Round(larger, mc));
        }
Exemplo n.º 9
0
        public BigDecimal ToBigDecimal(MathContext mc)
        {
            /* numerator and denominator individually rephrased
             */
            var n = new BigDecimal(Numerator);
            var d = new BigDecimal(Denominator);

            /* the problem with n.divide(d,mc) is that the apparent precision might be
             * smaller than what is set by mc if the value has a precise truncated representation.
             * 1/4 will appear as 0.25, independent of mc
             */
            return(BigMath.ScalePrecision(n.Divide(d, mc), mc));
        }
Exemplo n.º 10
0
        public static BigDecimal Pow(BigDecimal number, int n, MathContext mc)
        {
            // The ANSI standard X3.274-1996 algorithm
            int         m           = System.Math.Abs(n);
            int         mcPrecision = mc.Precision;
            int         elength     = (int)System.Math.Log10(m) + 1; // decimal digits in 'n'
            int         oneBitMask;                                  // mask of bits
            BigDecimal  accum;                                       // the single accumulator
            MathContext newPrecision = mc;                           // MathContext by default

            // In particular cases, it reduces the problem to call the other 'pow()'
            if ((n == 0) || ((number.IsZero) && (n > 0)))
            {
                return(Pow(number, n));
            }
            if ((m > 999999999) || ((mcPrecision == 0) && (n < 0)) ||
                ((mcPrecision > 0) && (elength > mcPrecision)))
            {
                // math.07=Invalid Operation
                throw new ArithmeticException(Messages.math07);                 //$NON-NLS-1$
            }
            if (mcPrecision > 0)
            {
                newPrecision = new MathContext(mcPrecision + elength + 1,
                                               mc.RoundingMode);
            }
            // The result is calculated as if 'n' were positive
            accum      = BigMath.Round(number, newPrecision);
            oneBitMask = Utils.HighestOneBit(m) >> 1;

            while (oneBitMask > 0)
            {
                accum = BigMath.Multiply(accum, accum, newPrecision);
                if ((m & oneBitMask) == oneBitMask)
                {
                    accum = BigMath.Multiply(accum, number, newPrecision);
                }
                oneBitMask >>= 1;
            }
            // If 'n' is negative, the value is divided into 'ONE'
            if (n < 0)
            {
                accum = Divide(BigDecimal.One, accum, newPrecision);
            }
            // The final value is rounded to the destination precision
            accum.InplaceRound(mc);
            return(accum);
        }
Exemplo n.º 11
0
        public static BigDecimal Subtract(BigDecimal value, BigDecimal subtrahend, MathContext mc)
        {
            if (subtrahend == null)
            {
                throw new ArgumentNullException("subtrahend");
            }
            if (mc == null)
            {
                throw new ArgumentNullException("mc");
            }

            long diffScale = subtrahend.Scale - (long)value.Scale;

            // Some operand is zero or the precision is infinity
            if ((subtrahend.IsZero) || (value.IsZero) || (mc.Precision == 0))
            {
                return(BigMath.Round(Subtract(value, subtrahend), mc));
            }

            // Now:   this != 0   and   subtrahend != 0
            if (subtrahend.AproxPrecision() < diffScale - 1)
            {
                // Cases where it is unnecessary to subtract two numbers with very different scales
                if (mc.Precision < value.AproxPrecision())
                {
                    var        thisSignum = value.Sign;
                    BigInteger tempBI;
                    if (thisSignum != subtrahend.Sign)
                    {
                        tempBI = Multiplication.MultiplyByPositiveInt(value.UnscaledValue, 10) +
                                 BigInteger.FromInt64(thisSignum);
                    }
                    else
                    {
                        tempBI = value.UnscaledValue - BigInteger.FromInt64(thisSignum);
                        tempBI = Multiplication.MultiplyByPositiveInt(tempBI, 10) +
                                 BigInteger.FromInt64(thisSignum * 9);
                    }
                    // Rounding the improved subtracting
                    var leftOperand = new BigDecimal(tempBI, value.Scale + 1);                     // it will be only the left operand (this)
                    return(BigMath.Round(leftOperand, mc));
                }
            }

            // No optimization is done
            return(BigMath.Round(Subtract(value, subtrahend), mc));
        }
Exemplo n.º 12
0
        public void MathContextConstruction()
        {
            String       a         = "-12380945E+61";
            BigDecimal   aNumber   = BigDecimal.Parse(a);
            int          precision = 6;
            RoundingMode rm        = RoundingMode.HalfDown;
            MathContext  mcIntRm   = new MathContext(precision, rm);
            MathContext  mcStr     = MathContext.Parse("precision=6 roundingMode=HALFDOWN");
            MathContext  mcInt     = new MathContext(precision);
            BigDecimal   res       = BigMath.Abs(aNumber, mcInt);

            Assert.Equal(res, BigDecimal.Parse("1.23809E+68"));

            Assert.Equal(mcIntRm, mcStr);

            Assert.Equal(mcInt.Equals(mcStr), false);

            Assert.Equal(mcIntRm.GetHashCode(), mcStr.GetHashCode());

            Assert.Equal(mcIntRm.ToString(), "precision=6 roundingMode=HalfDown");
        }
Exemplo n.º 13
0
        public void MathContextConstruction()
        {
            String       a         = "-12380945E+61";
            BigDecimal   aNumber   = BigDecimal.Parse(a);
            int          precision = 6;
            RoundingMode rm        = RoundingMode.HalfDown;
            MathContext  mcIntRm   = new MathContext(precision, rm);
            MathContext  mcStr     = MathContext.Parse("precision=6 roundingMode=HALFDOWN");
            MathContext  mcInt     = new MathContext(precision);
            BigDecimal   res       = aNumber.Abs(mcInt);

            Assert.AreEqual(res, BigDecimal.Parse("1.23809E+68"), "MathContext Constructor with int precision failed");

            Assert.AreEqual(mcIntRm, mcStr, "Equal MathContexts are not Equal ");

            Assert.AreEqual(mcInt.Equals(mcStr), false, "Different MathContext are reported as Equal ");

            Assert.AreEqual(mcIntRm.GetHashCode(), mcStr.GetHashCode(), "Equal MathContexts have different hashcodes ");

            Assert.AreEqual(mcIntRm.ToString(), "precision=6 roundingMode=HalfDown",
                            "MathContext.ToString() returning incorrect value");
        }
Exemplo n.º 14
0
 public BigDecimal Abs(MathContext mc)
 {
     return(BigMath.Sqrt(Norm(), mc));
 }
Exemplo n.º 15
0
        /**
         * Returns a new {@code BigDecimal} whose value is the integral part of
         * {@code this / divisor}. The quotient is rounded down towards zero to the
         * next integer. The rounding mode passed with the parameter {@code mc} is
         * not considered. But if the precision of {@code mc > 0} and the integral
         * part requires more digits, then an {@code ArithmeticException} is thrown.
         *
         * @param divisor
         *            value by which {@code this} is divided.
         * @param mc
         *            math context which determines the maximal precision of the
         *            result.
         * @return integral part of {@code this / divisor}.
         * @throws NullPointerException
         *             if {@code divisor == null} or {@code mc == null}.
         * @throws ArithmeticException
         *             if {@code divisor == 0}.
         * @throws ArithmeticException
         *             if {@code mc.getPrecision() > 0} and the result requires more
         *             digits to be represented.
         */

        public static BigDecimal DivideToIntegral(BigDecimal a, BigDecimal b, MathContext context)
        {
            return(BigDecimalMath.DivideToIntegralValue(a, b, context));
        }
Exemplo n.º 16
0
 public BigComplex Divide(BigComplex oth, MathContext mc)
 {
     /* lazy implementation: (x+iy)/(a+ib)= (x+iy)* 1/(a+ib) */
     return(Multiply(oth.Inverse(mc), mc));
 }
Exemplo n.º 17
0
 /**
  * Returns a new {@code BigDecimal} whose value is {@code this ^ n}. The
  * result is rounded according to the passed context {@code mc}.
  * <p>
  * Implementation Note: The implementation is based on the ANSI standard
  * X3.274-1996 algorithm.
  *
  * @param n
  *            exponent to which {@code this} is raised.
  * @param mc
  *            rounding mode and precision for the result of this operation.
  * @return {@code this ^ n}.
  * @throws ArithmeticException
  *             if {@code n < 0} or {@code n > 999999999}.
  */
 public static BigDecimal Pow(BigDecimal number, int exp, MathContext context)
 {
     return(BigDecimalMath.Pow(number, exp, context));
 }
Exemplo n.º 18
0
        /**
         * Returns a new {@code BigDecimal} whose value is the absolute value of
         * {@code this}. The result is rounded according to the passed context
         * {@code mc}.
         *
         * @param mc
         *            rounding mode and precision for the result of this operation.
         * @return {@code abs(this)}
         */

        public static BigDecimal Abs(BigDecimal value, MathContext mc)
        {
            return(Abs(Round(value, mc)));
        }
Exemplo n.º 19
0
        public static BigDecimal DivideAndRemainder(BigDecimal dividend, BigDecimal divisor, MathContext mc, out BigDecimal remainder)
        {
            var quotient = DivideToIntegralValue(dividend, divisor, mc);

            remainder = Subtract(dividend, Multiply(quotient, divisor));
            return(quotient);
        }
Exemplo n.º 20
0
        public static BigDecimal DivideToIntegralValue(BigDecimal dividend, BigDecimal divisor, MathContext mc)
        {
            int        mcPrecision   = mc.Precision;
            int        diffPrecision = dividend.Precision - divisor.Precision;
            int        lastPow       = BigDecimal.TenPow.Length - 1;
            long       diffScale     = (long)dividend.Scale - divisor.Scale;
            long       newScale      = diffScale;
            long       quotPrecision = diffPrecision - diffScale + 1;
            BigInteger quotient;
            BigInteger remainder;

            // In special cases it call the dual method
            if ((mcPrecision == 0) || (dividend.IsZero) || (divisor.IsZero))
            {
                return(DivideToIntegralValue(dividend, divisor));
            }
            // Let be:   this = [u1,s1]   and   divisor = [u2,s2]
            if (quotPrecision <= 0)
            {
                quotient = BigInteger.Zero;
            }
            else if (diffScale == 0)
            {
                // CASE s1 == s2:  to calculate   u1 / u2
                quotient = dividend.UnscaledValue / divisor.UnscaledValue;
            }
            else if (diffScale > 0)
            {
                // CASE s1 >= s2:  to calculate   u1 / (u2 * 10^(s1-s2)
                quotient = dividend.UnscaledValue / (divisor.UnscaledValue * Multiplication.PowerOf10(diffScale));
                // To chose  10^newScale  to get a quotient with at least 'mc.precision()' digits
                newScale = System.Math.Min(diffScale, System.Math.Max(mcPrecision - quotPrecision + 1, 0));
                // To calculate: (u1 / (u2 * 10^(s1-s2)) * 10^newScale
                quotient = quotient * Multiplication.PowerOf10(newScale);
            }
            else
            {
                // CASE s2 > s1:

                /* To calculate the minimum power of ten, such that the quotient
                 *   (u1 * 10^exp) / u2   has at least 'mc.precision()' digits. */
                long exp = System.Math.Min(-diffScale, System.Math.Max((long)mcPrecision - diffPrecision, 0));
                long compRemDiv;
                // Let be:   (u1 * 10^exp) / u2 = [q,r]
                quotient = BigMath.DivideAndRemainder(dividend.UnscaledValue * Multiplication.PowerOf10(exp),
                                                      divisor.UnscaledValue, out remainder);
                newScale += exp;                 // To fix the scale
                exp       = -newScale;           // The remaining power of ten
                // If after division there is a remainder...
                if ((remainder.Sign != 0) && (exp > 0))
                {
                    // Log10(r) + ((s2 - s1) - exp) > mc.precision ?
                    compRemDiv = (new BigDecimal(remainder)).Precision
                                 + exp - divisor.Precision;
                    if (compRemDiv == 0)
                    {
                        // To calculate:  (r * 10^exp2) / u2
                        remainder  = (remainder * Multiplication.PowerOf10(exp)) / divisor.UnscaledValue;
                        compRemDiv = System.Math.Abs(remainder.Sign);
                    }
                    if (compRemDiv > 0)
                    {
                        // The quotient won't fit in 'mc.precision()' digits
                        // math.06=Division impossible
                        throw new ArithmeticException(Messages.math06);                         //$NON-NLS-1$
                    }
                }
            }
            // Fast return if the quotient is zero
            if (quotient.Sign == 0)
            {
                return(BigDecimal.GetZeroScaledBy(diffScale));
            }
            BigInteger strippedBI      = quotient;
            BigDecimal integralValue   = new BigDecimal(quotient);
            long       resultPrecision = integralValue.Precision;
            int        i = 1;

            // To strip trailing zeros until the specified precision is reached
            while (!BigInteger.TestBit(strippedBI, 0))
            {
                quotient = BigMath.DivideAndRemainder(strippedBI, BigDecimal.TenPow[i], out remainder);
                if ((remainder.Sign == 0) &&
                    ((resultPrecision - i >= mcPrecision) ||
                     (newScale - i >= diffScale)))
                {
                    resultPrecision -= i;
                    newScale        -= i;
                    if (i < lastPow)
                    {
                        i++;
                    }
                    strippedBI = quotient;
                }
                else
                {
                    if (i == 1)
                    {
                        break;
                    }
                    i = 1;
                }
            }
            // To check if the result fit in 'mc.precision()' digits
            if (resultPrecision > mcPrecision)
            {
                // math.06=Division impossible
                throw new ArithmeticException(Messages.math06);                 //$NON-NLS-1$
            }
            integralValue.Scale = BigDecimal.ToIntScale(newScale);
            integralValue.SetUnscaledValue(strippedBI);
            return(integralValue);
        }
Exemplo n.º 21
0
        /**
         * Returns a new {@code BigDecimal} whose value is {@code this / divisor}.
         * The result is rounded according to the passed context {@code mc}. If the
         * passed math context specifies precision {@code 0}, then this call is
         * equivalent to {@code this.divide(divisor)}.
         *
         * @param divisor
         *            value by which {@code this} is divided.
         * @param mc
         *            rounding mode and precision for the result of this operation.
         * @return {@code this / divisor}.
         * @throws NullPointerException
         *             if {@code divisor == null} or {@code mc == null}.
         * @throws ArithmeticException
         *             if {@code divisor == 0}.
         * @throws ArithmeticException
         *             if {@code mc.getRoundingMode() == UNNECESSARY} and rounding
         *             is necessary according {@code mc.getPrecision()}.
         */

        public static BigDecimal Divide(BigDecimal a, BigDecimal b, MathContext context)
        {
            return(BigDecimalMath.Divide(a, b, context));
        }
Exemplo n.º 22
0
 /// <summary>
 /// Adds a value to the current instance of <see cref="BigDecimal"/>,
 /// rounding the result according to the provided context.
 /// </summary>
 /// <param name="augend">The value to be added to this instance.</param>
 /// <param name="mc">The rounding mode and precision for the result of
 /// this operation.</param>
 /// <returns>
 /// Returns a new <see cref="BigDecimal"/> whose value is <c>this + <paramref name="augend"/></c>.
 /// </returns>
 /// <exception cref="ArgumentNullException">
 /// If the given <paramref name="augend"/> or <paramref name="mc"/> is <c>null</c>.
 /// </exception>
 public static BigDecimal Add(BigDecimal value, BigDecimal augend, MathContext mc)
 {
     return(BigDecimalMath.Add(value, augend, mc));
 }
Exemplo n.º 23
0
 /// <remarks>
 /// Returns a new <see cref="BigDecimal"/> whose value is <c>+this</c>.
 /// </remarks>
 /// <param name="mc">Rounding mode and precision for the result of this operation.</param>
 /// <remarks>
 /// The result is rounded according to the passed context <paramref name="mc"/>.
 /// </remarks>
 /// <returns>
 /// Returns this decimal value rounded.
 /// </returns>
 public static BigDecimal Plus(BigDecimal number, MathContext mc)
 {
     return(Round(number, mc));
 }
Exemplo n.º 24
0
        /**
         * Returns a new {@code BigDecimal} whose value is the {@code -this}. The
         * result is rounded according to the passed context {@code mc}.
         *
         * @param mc
         *            rounding mode and precision for the result of this operation.
         * @return {@code -this}
         */

        public static BigDecimal Negate(BigDecimal number, MathContext mc)
        {
            return(Negate(Round(number, mc)));
        }
Exemplo n.º 25
0
        public static BigDecimal Divide(BigDecimal dividend, BigDecimal divisor, MathContext mc)
        {
            /* Calculating how many zeros must be append to 'dividend'
             * to obtain a  quotient with at least 'mc.precision()' digits */
            long traillingZeros = mc.Precision + 2L
                                  + divisor.AproxPrecision() - dividend.AproxPrecision();
            long       diffScale = (long)dividend.Scale - divisor.Scale;
            long       newScale  = diffScale;                  // scale of the final quotient
            int        compRem;                                // to compare the remainder
            int        i       = 1;                            // index
            int        lastPow = BigDecimal.TenPow.Length - 1; // last power of ten
            BigInteger integerQuot;                            // for temporal results
            BigInteger quotient = dividend.UnscaledValue;
            BigInteger remainder;

            // In special cases it reduces the problem to call the dual method
            if ((mc.Precision == 0) || (dividend.IsZero) || (divisor.IsZero))
            {
                return(Divide(dividend, divisor));
            }

            if (traillingZeros > 0)
            {
                // To append trailing zeros at end of dividend
                quotient  = dividend.UnscaledValue * Multiplication.PowerOf10(traillingZeros);
                newScale += traillingZeros;
            }
            quotient    = BigMath.DivideAndRemainder(quotient, divisor.UnscaledValue, out remainder);
            integerQuot = quotient;
            // Calculating the exact quotient with at least 'mc.precision()' digits
            if (remainder.Sign != 0)
            {
                // Checking if:   2 * remainder >= divisor ?
                compRem = remainder.ShiftLeftOneBit().CompareTo(divisor.UnscaledValue);
                // quot := quot * 10 + r;     with 'r' in {-6,-5,-4, 0,+4,+5,+6}
                integerQuot = (integerQuot * BigInteger.Ten) +
                              BigInteger.FromInt64(quotient.Sign * (5 + compRem));
                newScale++;
            }
            else
            {
                // To strip trailing zeros until the preferred scale is reached
                while (!BigInteger.TestBit(integerQuot, 0))
                {
                    quotient = BigMath.DivideAndRemainder(integerQuot, BigDecimal.TenPow[i], out remainder);
                    if ((remainder.Sign == 0) &&
                        (newScale - i >= diffScale))
                    {
                        newScale -= i;
                        if (i < lastPow)
                        {
                            i++;
                        }
                        integerQuot = quotient;
                    }
                    else
                    {
                        if (i == 1)
                        {
                            break;
                        }
                        i = 1;
                    }
                }
            }
            // To perform rounding
            return(new BigDecimal(integerQuot, BigDecimal.ToIntScale(newScale), mc));
        }
Exemplo n.º 26
0
 /// <summary>
 /// Subtracts the given value from this instance of <see cref="BigDecimal"/>.
 /// </summary>
 /// <remarks>
 /// <para>
 /// This overload rounds the result of the operation to the <paramref name="mc">context</paramref>
 /// provided as argument.
 /// </para>
 /// </remarks>
 /// <param name="subtrahend">The value to be subtracted from this <see cref="BigDecimal"/>.</param>
 /// <param name="mc">The context used to round the result of this operation.</param>
 /// <returns>
 /// Returns an instance of <see cref="BigDecimal"/> that is the result of the
 /// subtraction of the given <paramref name="subtrahend"/> from this instance.
 /// </returns>
 /// <exception cref="ArgumentNullException">
 /// If either of the given <paramref name="subtrahend"/> or <paramref name="mc"/> are <c>null</c>.
 /// </exception>
 public static BigDecimal Subtract(BigDecimal value, BigDecimal subtrahend, MathContext mc)
 {
     return(BigDecimalMath.Subtract(value, subtrahend, mc));
 }