コード例 #1
0
ファイル: Primality.cs プロジェクト: bugbit/CASSharp
        /**
         * The Miller-Rabin primality test.
         *
         * @param n the input number to be tested.
         * @param t the number of trials.
         * @return {@code false} if the number is definitely compose, otherwise
         *         {@code true} with probability {@code 1 - 4<sup>(-t)</sup>}.
         * @ar.org.fitc.ref "D. Knuth, The Art of Computer Programming Vo.2, Section
         *                  4.5.4., Algorithm P"
         */
        private static bool MillerRabin(BigInteger n, int t, CancellationToken argCancelToken)
        {
            argCancelToken.ThrowIfCancellationRequested();

            // PRE: n >= 0, t >= 0
            BigInteger x;                               // x := UNIFORM{2...n-1}
            BigInteger y;                               // y := x^(q * 2^j) mod n
            BigInteger n_minus_1 = n - BigInteger.One;  // n-1
            int        bitLength = n_minus_1.BitLength; // ~ log2(n-1)
                                                        // (q,k) such that: n-1 = q * 2^k and q is odd
            int        k   = n_minus_1.LowestSetBit;
            BigInteger q   = n_minus_1 >> k;
            Random     rnd = new Random();

            for (int i = 0; i < t; i++)
            {
                argCancelToken.ThrowIfCancellationRequested();
                // To generate a witness 'x', first it use the primes of table
                if (i < primes.Length)
                {
                    x = BIprimes[i];
                }
                else
                {/*
                  * It generates random witness only if it's necesssary. Note
                  * that all methods would call Miller-Rabin with t <= 50 so
                  * this part is only to do more robust the algorithm
                  */
                    do
                    {
                        argCancelToken.ThrowIfCancellationRequested();
                        x = new BigInteger(bitLength, rnd);
                    } while ((x.CompareTo(n) >= BigInteger.EQUALS) || (x.Sign == 0) ||
                             x.IsOne);
                }
                y = BigMath.ModPow(x, q, n);
                if (y.IsOne || y.Equals(n_minus_1))
                {
                    continue;
                }
                for (int j = 1; j < k; j++)
                {
                    argCancelToken.ThrowIfCancellationRequested();
                    if (y.Equals(n_minus_1))
                    {
                        continue;
                    }
                    y = (y * y) % n;
                    if (y.IsOne)
                    {
                        return(false);
                    }
                }
                if (!y.Equals(n_minus_1))
                {
                    return(false);
                }
            }
            return(true);
        }
コード例 #2
0
        public void MultiplyBigDecimal()
        {
            BigDecimal multi1 = new BigDecimal(value, 5);
            BigDecimal multi2 = new BigDecimal(2.345D);
            BigDecimal result = BigMath.Multiply(multi1, multi2);

            Assert.True(result.ToString().StartsWith("289.51154260") && result.Scale == multi1.Scale + multi2.Scale,
                        "123.45908 * 2.345 is not correct: " + result);
            multi1 = BigDecimal.Parse("34656");
            multi2 = BigDecimal.Parse("-2");
            result = BigMath.Multiply(multi1, multi2);
            Assert.True(result.ToString().Equals("-69312") && result.Scale == 0, "34656 * 2 is not correct");
            multi1 = new BigDecimal(-2.345E-02);
            multi2 = new BigDecimal(-134E130);
            result = BigMath.Multiply(multi1, multi2);
            Assert.True(result.ToDouble() == 3.1422999999999997E130 && result.Scale == multi1.Scale + multi2.Scale,
                        "-2.345E-02 * -134E130 is not correct " + result.ToDouble());
            multi1 = BigDecimal.Parse("11235");
            multi2 = BigDecimal.Parse("0");
            result = BigMath.Multiply(multi1, multi2);
            Assert.True(result.ToDouble() == 0 && result.Scale == 0, "11235 * 0 is not correct");
            multi1 = BigDecimal.Parse("-0.00234");
            multi2 = new BigDecimal(13.4E10);
            result = BigMath.Multiply(multi1, multi2);
            Assert.True(result.ToDouble() == -313560000 && result.Scale == multi1.Scale + multi2.Scale,
                        "-0.00234 * 13.4E10 is not correct");
        }
コード例 #3
0
 public void RemainderBigInteger()
 {
     Assert.Throws <ArithmeticException>(() => BigMath.Remainder(largePos, zero));
     Assert.Throws <ArithmeticException>(() => BigMath.Remainder(bi1, zero));
     Assert.Throws <ArithmeticException>(() => BigMath.Remainder(-bi3, zero));
     Assert.Throws <ArithmeticException>(() => BigMath.Remainder(zero, zero));
 }
コード例 #4
0
        private void TestDiv(BigInteger i1, BigInteger i2)
        {
            BigInteger q = i1 / i2;
            BigInteger r = BigMath.Remainder(i1, i2);
            BigInteger remainder;
            BigInteger quotient = BigMath.DivideAndRemainder(i1, i2, out remainder);

            Assert.True(q.Equals(quotient), "Divide and DivideAndRemainder do not agree");
            Assert.True(r.Equals(remainder), "Remainder and DivideAndRemainder do not agree");
            Assert.True(q.Sign != 0 || q.Equals(zero), "signum and equals(zero) do not agree on quotient");
            Assert.True(r.Sign != 0 || r.Equals(zero), "signum and equals(zero) do not agree on remainder");
            Assert.True(q.Sign == 0 || q.Sign == i1.Sign * i2.Sign, "wrong sign on quotient");
            Assert.True(r.Sign == 0 || r.Sign == i1.Sign, "wrong sign on remainder");
            Assert.True(BigMath.Abs(r).CompareTo(BigMath.Abs(i2)) < 0, "remainder out of range");
            Assert.True(((BigMath.Abs(q) + one) * BigMath.Abs(i2)).CompareTo(BigMath.Abs(i1)) > 0, "quotient too small");
            Assert.True((BigMath.Abs(q) * BigMath.Abs(i2)).CompareTo(BigMath.Abs(i1)) <= 0, "quotient too large");
            BigInteger p = q * i2;
            BigInteger a = p + r;

            Assert.True(a.Equals(i1), "(a/b)*b+(a%b) != a");
            try {
                BigInteger mod = i1 % i2;
                Assert.True(mod.Sign >= 0, "mod is negative");
                Assert.True(BigMath.Abs(mod).CompareTo(BigMath.Abs(i2)) < 0, "mod out of range");
                Assert.True(r.Sign < 0 || r.Equals(mod), "positive remainder == mod");
                Assert.True(r.Sign >= 0 || r.Equals(mod - i2), "negative remainder == mod - divisor");
            } catch (ArithmeticException e) {
                Assert.True(i2.Sign <= 0, "mod fails on negative divisor only");
            }
        }
コード例 #5
0
        public void AndNotBigInteger()
        {
            foreach (BigInteger[] element in booleanPairs)
            {
                BigInteger i1 = element[0], i2 = element[1];
                BigInteger res = BigMath.AndNot(i1, i2);
                int        len = System.Math.Max(i1.BitLength, i2.BitLength) + 66;
                for (int i = 0; i < len; i++)
                {
                    Assert.True((BigInteger.TestBit(i1, i) && !BigInteger.TestBit(i2, i)) == BigInteger.TestBit(res, i), "andNot");
                }

                // asymmetrical
                i1  = element[1];
                i2  = element[0];
                res = BigMath.AndNot(i1, i2);
                for (int i = 0; i < len; i++)
                {
                    Assert.True((BigInteger.TestBit(i1, i) && !BigInteger.TestBit(i2, i)) == BigInteger.TestBit(res, i), "andNot reversed");
                }
            }

            Assert.Throws <NullReferenceException>(() => BigMath.AndNot(BigInteger.Zero, null));

            BigInteger bi = new BigInteger(0, new byte[] { });

            Assert.Equal(BigInteger.Zero, BigMath.AndNot(bi, BigInteger.Zero));
        }
コード例 #6
0
        public void ToDouble()
        {
            BigDecimal bigDB = new BigDecimal(-1.234E-112);

            //		Commenting out this part because it causes an endless loop (see HARMONY-319 and HARMONY-329)
            //		Assert.True(
            //				"the double representation of this BigDecimal is not correct",
            //				bigDB.ToDouble() == -1.234E-112);
            bigDB = new BigDecimal(5.00E-324);
            Assert.True(bigDB.ToDouble() == 5.00E-324, "the double representation of bigDecimal is not correct");
            bigDB = new BigDecimal(1.79E308);
            Assert.True(bigDB.ToDouble() == 1.79E308 && bigDB.Scale == 0,
                        "the double representation of bigDecimal is not correct");
            bigDB = new BigDecimal(-2.33E102);
            Assert.True(bigDB.ToDouble() == -2.33E102 && bigDB.Scale == 0,
                        "the double representation of bigDecimal -2.33E102 is not correct");
            bigDB = new BigDecimal(Double.MaxValue);
            bigDB = BigMath.Add(bigDB, bigDB);
            Assert.True(bigDB.ToDouble() == Double.PositiveInfinity,
                        "a  + number out of the double range should return infinity");
            bigDB = new BigDecimal(-Double.MaxValue);
            bigDB = BigMath.Add(bigDB, bigDB);
            Assert.True(bigDB.ToDouble() == Double.NegativeInfinity,
                        "a  - number out of the double range should return neg infinity");
        }
コード例 #7
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()));
            }
        }
コード例 #8
0
 public void Abs()
 {
     Assert.True(BigMath.Abs(-aZillion).Equals(BigMath.Abs(aZillion)), "Invalid number returned for zillion");
     Assert.True(BigMath.Abs(-zero).Equals(zero), "Invalid number returned for zero neg");
     Assert.True(BigMath.Abs(zero).Equals(zero), "Invalid number returned for zero");
     Assert.True(BigMath.Abs(-two).Equals(two), "Invalid number returned for two");
 }
コード例 #9
0
        /**
         * Returns this {@code BigDecimal} as a big integer instance if it has no
         * fractional part. If this {@code BigDecimal} has a fractional part, i.e.
         * if rounding would be necessary, an {@code ArithmeticException} is thrown.
         *
         * @return this {@code BigDecimal} as a big integer value.
         * @throws ArithmeticException
         *             if rounding is necessary.
         */

        public BigInteger ToBigIntegerExact()
        {
            if ((_scale == 0) || (IsZero))
            {
                return(GetUnscaledValue());
            }
            else if (_scale < 0)
            {
                return(GetUnscaledValue() * Multiplication.PowerOf10(-(long)_scale));
            }
            else
            {
                // (scale > 0)
                BigInteger integer;
                BigInteger fraction;

                // An optimization before do a heavy division
                if ((_scale > AproxPrecision()) || (_scale > GetUnscaledValue().LowestSetBit))
                {
                    // math.08=Rounding necessary
                    throw new ArithmeticException(Messages.math08);                     //$NON-NLS-1$
                }

                integer = BigMath.DivideAndRemainder(GetUnscaledValue(), Multiplication.PowerOf10(_scale), out fraction);
                if (fraction.Sign != 0)
                {
                    // It exists a non-zero fractional part
                    // math.08=Rounding necessary
                    throw new ArithmeticException(Messages.math08);                     //$NON-NLS-1$
                }

                return(integer);
            }
        }
コード例 #10
0
        public void DivideAndRemainderBigInteger()
        {
            BigInteger remainder;

            Assert.Throws <ArithmeticException>(() => BigMath.DivideAndRemainder(largePos, zero, out remainder));
            Assert.Throws <ArithmeticException>(() => BigMath.DivideAndRemainder(bi1, zero, out remainder));
            Assert.Throws <ArithmeticException>(() => BigMath.DivideAndRemainder(-bi3, zero, out remainder));
            Assert.Throws <ArithmeticException>(() => BigMath.DivideAndRemainder(zero, zero, out remainder));
        }
コード例 #11
0
        public void MinBigDecimal()
        {
            BigDecimal min1 = new BigDecimal(-12345.4D);
            BigDecimal min2 = new BigDecimal(-12345.39D);

            Assert.True(BigMath.Min(min1, min2).Equals(min1), "-12345.39 should have been returned");
            min1 = new BigDecimal(value2, 5);
            min2 = new BigDecimal(value2, 0);
            Assert.True(BigMath.Min(min1, min2).Equals(min1), "123345.6 should have been returned");
        }
コード例 #12
0
        public void Abs()
        {
            BigDecimal big    = BigDecimal.Parse("-1234");
            BigDecimal bigabs = BigMath.Abs(big);

            Assert.True(bigabs.ToString().Equals("1234"), "the absolute value of -1234 is not 1234");
            big    = new BigDecimal(BigInteger.Parse("2345"), 2);
            bigabs = BigMath.Abs(big);
            Assert.True(bigabs.ToString().Equals("23.45"), "the absolute value of 23.45 is not 23.45");
        }
コード例 #13
0
        // TODO: must be verified
        public decimal ToDecimal()
        {
            var scaleDivisor = BigMath.Pow(BigInteger.FromInt64(10), _scale);
            var remainder    = BigMath.Remainder(GetUnscaledValue(), scaleDivisor);
            var scaledValue  = GetUnscaledValue() / scaleDivisor;

            var leftOfDecimal  = (decimal)scaledValue;
            var rightOfDecimal = (remainder) / ((decimal)scaleDivisor);

            return(leftOfDecimal + rightOfDecimal);
        }
コード例 #14
0
        public static BigInteger Mod(BigInteger value, BigInteger m)
        {
            if (m.Sign <= 0)
            {
                // math.18=BigInteger: modulus not positive
                throw new ArithmeticException(Messages.math18);                 //$NON-NLS-1$
            }
            BigInteger rem = BigMath.Remainder(value, m);

            return((rem.Sign < 0) ? rem + m : rem);
        }
コード例 #15
0
        /** @see BigInteger#ToDouble() */

        public static double BigInteger2Double(BigInteger val)
        {
            // val.bitLength() < 64
            if ((val.numberLength < 2) ||
                ((val.numberLength == 2) && (val.Digits[1] > 0)))
            {
                return(val.ToInt64());
            }
            // val.bitLength() >= 33 * 32 > 1024
            if (val.numberLength > 32)
            {
                return((val.Sign > 0) ? Double.PositiveInfinity
                                                : Double.NegativeInfinity);
            }
            int  bitLen   = BigMath.Abs(val).BitLength;
            long exponent = bitLen - 1;
            int  delta    = bitLen - 54;
            // We need 54 top bits from this, the 53th bit is always 1 in lVal.
            long lVal = (BigMath.Abs(val) >> delta).ToInt64();

            /*
             * Take 53 bits from lVal to mantissa. The least significant bit is
             * needed for rounding.
             */
            long mantissa = lVal & 0x1FFFFFFFFFFFFFL;

            if (exponent == 1023)
            {
                if (mantissa == 0X1FFFFFFFFFFFFFL)
                {
                    return((val.Sign > 0) ? Double.PositiveInfinity
                                                        : Double.NegativeInfinity);
                }
                if (mantissa == 0x1FFFFFFFFFFFFEL)
                {
                    return((val.Sign > 0) ? Double.MaxValue : -Double.MaxValue);
                }
            }
            // Round the mantissa
            if (((mantissa & 1) == 1) &&
                (((mantissa & 2) == 2) || BitLevel.NonZeroDroppedBits(delta,
                                                                      val.Digits)))
            {
                mantissa += 2;
            }
            mantissa >>= 1;             // drop the rounding bit
            // long resSign = (val.sign < 0) ? 0x8000000000000000L : 0;
            long resSign = (val.Sign < 0) ? Int64.MinValue : 0;

            exponent = ((1023 + exponent) << 52) & 0x7FF0000000000000L;
            long result = resSign | exponent | mantissa;

            return(BitConverter.Int64BitsToDouble(result));
        }
コード例 #16
0
        public void SetScaleI()
        {
            // rounding mode defaults to zero
            BigDecimal setScale1 = new BigDecimal(value, 3);
            BigDecimal setScale2 = BigMath.Scale(setScale1, 5);
            BigInteger setresult = BigInteger.Parse("1234590800");

            Assert.True(setScale2.UnscaledValue.Equals(setresult) && setScale2.Scale == 5,
                        "the number 12345.908 after setting scale is wrong");

            Assert.Throws <ArithmeticException>(() => BigMath.Scale(setScale1, 2, RoundingMode.Unnecessary));
        }
コード例 #17
0
        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));
        }
コード例 #18
0
ファイル: Rational.cs プロジェクト: ArsenShnurkov/deveel-math
        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));
        }
コード例 #19
0
        public void MaxBigDecimal()
        {
            BigDecimal max1 = new BigDecimal(value2, 1);
            BigDecimal max2 = new BigDecimal(value2, 4);

            Assert.True(BigMath.Max(max1, max2).Equals(max1), "1233456000.0 is not greater than 1233456");
            max1 = new BigDecimal(-1.224D);
            max2 = new BigDecimal(-1.2245D);
            Assert.True(BigMath.Max(max1, max2).Equals(max1), "-1.224 is not greater than -1.2245");
            max1 = new BigDecimal(123E18);
            max2 = new BigDecimal(123E19);
            Assert.True(BigMath.Max(max1, max2).Equals(max2), "123E19 is the not the max");
        }
コード例 #20
0
        public void AddBigDecimal()
        {
            BigDecimal add1 = BigDecimal.Parse("23.456");
            BigDecimal add2 = BigDecimal.Parse("3849.235");
            BigDecimal sum  = BigMath.Add(add1, add2);

            Assert.True(sum.UnscaledValue.ToString().Equals("3872691") && sum.Scale == 3,
                        "the sum of 23.456 + 3849.235 is wrong");
            Assert.True(sum.ToString().Equals("3872.691"), "the sum of 23.456 + 3849.235 is not printed correctly");
            BigDecimal add3 = new BigDecimal(12.34E02D);

            Assert.True((BigMath.Add(add1, add3)).ToString().Equals("1257.456"), "the sum of 23.456 + 12.34E02 is not printed correctly");
        }
コード例 #21
0
        public void DivideBigDecimalII()
        {
            BigDecimal divd1 = new BigDecimal(value2, 4);
            BigDecimal divd2 = BigDecimal.Parse("0.0023");
            BigDecimal divd3 = BigMath.Divide(divd1, divd2, 3, RoundingMode.HalfUp);

            Assert.True(divd3.ToString().Equals("536285217.391") && divd3.Scale == 3, "1233456/0.0023 is not correct");
            divd2 = new BigDecimal(1345.5E-02D);
            divd3 = BigMath.Divide(divd1, divd2, 0, RoundingMode.Down);
            Assert.True(divd3.ToString().Equals("91672") && divd3.Scale == 0,
                        "1233456/13.455 is not correct or does not have the correct scale");
            divd2 = new BigDecimal(0000D);

            Assert.Throws <ArithmeticException>(() => BigMath.Divide(divd1, divd2, 4, RoundingMode.Down));
        }
コード例 #22
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);
        }
コード例 #23
0
        public void DivideBigDecimalI()
        {
            BigDecimal divd1 = new BigDecimal(value, 2);
            BigDecimal divd2 = BigDecimal.Parse("2.335");
            BigDecimal divd3 = BigMath.Divide(divd1, divd2, RoundingMode.Up);

            Assert.True(divd3.ToString().Equals("52873.27") && divd3.Scale == divd1.Scale, "123459.08/2.335 is not correct");
            Assert.True(divd3.UnscaledValue.ToString().Equals("5287327"),
                        "the unscaledValue representation of 123459.08/2.335 is not correct");
            divd2 = new BigDecimal(123.4D);
            divd3 = BigMath.Divide(divd1, divd2, RoundingMode.Down);
            Assert.True(divd3.ToString().Equals("1000.47") && divd3.Scale == 2, "123459.08/123.4  is not correct");
            divd2 = new BigDecimal(000D);

            Assert.Throws <ArithmeticException>(() => BigMath.Divide(divd1, divd2, RoundingMode.Down));
        }
コード例 #24
0
        /**
         * Multiplies a number by a power of five.
         * This method is used in {@code BigDecimal} class.
         * @param val the number to be multiplied
         * @param exp a positive {@code int} exponent
         * @return {@code val * 5<sup>exp</sup>}
         */

        public static BigInteger MultiplyByFivePow(BigInteger val, int exp)
        {
            // PRE: exp >= 0
            if (exp < FivePows.Length)
            {
                return(MultiplyByPositiveInt(val, FivePows[exp]));
            }
            else if (exp < BigFivePows.Length)
            {
                return(val * BigFivePows[exp]);
            }
            else                // Large powers of five
            {
                return(val * BigMath.Pow(BigFivePows[1], exp));
            }
        }
コード例 #25
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));
        }
コード例 #26
0
        public void StripTrailingZero()
        {
            BigDecimal sixhundredtest = BigDecimal.Parse("600.0");

            Assert.True(BigMath.StripTrailingZeros(sixhundredtest).Scale == -2, "stripTrailingZero failed for 600.0");

            /* Single digit, no trailing zero, odd number */
            BigDecimal notrailingzerotest = BigDecimal.Parse("1");

            Assert.True(BigMath.StripTrailingZeros(notrailingzerotest).Scale == 0, "stripTrailingZero failed for 1");

            /* Zero */
            //regression for HARMONY-4623, NON-BUG DIFF with RI
            BigDecimal zerotest = BigDecimal.Parse("0.0000");

            Assert.True(BigMath.StripTrailingZeros(zerotest).Scale == 0, "stripTrailingZero failed for 0.0000");
        }
コード例 #27
0
        public static BigDecimal Pow(BigDecimal number, int n)
        {
            if (n == 0)
            {
                return(BigDecimal.One);
            }
            if ((n < 0) || (n > 999999999))
            {
                // math.07=Invalid Operation
                throw new ArithmeticException(Messages.math07);                 //$NON-NLS-1$
            }
            long newScale = number.Scale * (long)n;

            // Let be: this = [u,s]   so:  this^n = [u^n, s*n]
            return((number.IsZero)
                                ? BigDecimal.GetZeroScaledBy(newScale)
                                : new BigDecimal(BigMath.Pow(number.UnscaledValue, n), BigDecimal.ToIntScale(newScale)));
        }
コード例 #28
0
        public static BigDecimal DivideBigIntegers(BigInteger scaledDividend, BigInteger scaledDivisor, int scale,
                                                   RoundingMode roundingMode)
        {
            BigInteger remainder;
            BigInteger quotient = BigMath.DivideAndRemainder(scaledDividend, scaledDivisor, out remainder);

            if (remainder.Sign == 0)
            {
                return(new BigDecimal(quotient, scale));
            }
            int sign = scaledDividend.Sign * scaledDivisor.Sign;
            int compRem;             // 'compare to remainder'

            if (scaledDivisor.BitLength < 63)
            {
                // 63 in order to avoid out of long after <<1
                long rem     = remainder.ToInt64();
                long divisor = scaledDivisor.ToInt64();
                compRem = BigDecimal.LongCompareTo(System.Math.Abs(rem) << 1, System.Math.Abs(divisor));
                // To look if there is a carry
                compRem = BigDecimal.RoundingBehavior(BigInteger.TestBit(quotient, 0) ? 1 : 0,
                                                      sign * (5 + compRem), roundingMode);
            }
            else
            {
                // Checking if:  remainder * 2 >= scaledDivisor
                compRem = BigMath.Abs(remainder).ShiftLeftOneBit().CompareTo(BigMath.Abs(scaledDivisor));
                compRem = BigDecimal.RoundingBehavior(BigInteger.TestBit(quotient, 0) ? 1 : 0,
                                                      sign * (5 + compRem), roundingMode);
            }
            if (compRem != 0)
            {
                if (quotient.BitLength < 63)
                {
                    return(BigDecimal.Create(quotient.ToInt64() + compRem, scale));
                }
                quotient += BigInteger.FromInt64(compRem);
                return(new BigDecimal(quotient, scale));
            }
            // Constructing the result with the appropriate unscaled value
            return(new BigDecimal(quotient, scale));
        }
コード例 #29
0
        public void MovePointRightI()
        {
            BigDecimal movePtRight  = BigDecimal.Parse("-1.58796521458");
            BigDecimal alreadyMoved = BigMath.MovePointRight(movePtRight, 8);

            Assert.True(alreadyMoved.Scale == 3 && alreadyMoved.ToString().Equals("-158796521.458"),
                        "move point right 8 failed");
            movePtRight  = new BigDecimal(value, 2);
            alreadyMoved = BigMath.MovePointRight(movePtRight, 4);
            Assert.True(alreadyMoved.Scale == 0 && alreadyMoved.ToString().Equals("1234590800"), "move point right 4 failed");
            movePtRight  = new BigDecimal(134E12);
            alreadyMoved = BigMath.MovePointRight(movePtRight, 2);
            Assert.True(alreadyMoved.Scale == 0 && alreadyMoved.ToString().Equals("13400000000000000"),
                        "move point right 2 failed");
            movePtRight  = new BigDecimal(-3.4E-10);
            alreadyMoved = BigMath.MovePointRight(movePtRight, 5);
            Assert.True(alreadyMoved.Scale == movePtRight.Scale - 5 && alreadyMoved.ToDouble() == -0.000034,
                        "move point right 5 failed");
            alreadyMoved = BigMath.MovePointRight(alreadyMoved, -5);
            Assert.True(alreadyMoved.Equals(movePtRight), "move point right -5 failed");
        }
コード例 #30
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");
        }