コード例 #1
0
        public void MmodInverseBigInteger()
        {
            BigInteger a = zero, mod, inv;

            for (int j = 3; j < 50; j++)
            {
                mod = BigInteger.FromInt64(j);
                for (int i = -j + 1; i < j; i++)
                {
                    try {
                        a   = BigInteger.FromInt64(i);
                        inv = BigMath.ModInverse(a, mod);
                        Assert.True(one.Equals(((a * inv) % mod)), "bad inverse: " + a + " inv mod " + mod + " equals " + inv);
                        Assert.True(inv.CompareTo(mod) < 0, "inverse greater than modulo: " + a + " inv mod " + mod + " equals " + inv);
                        Assert.True(inv.CompareTo(BigInteger.Zero) >= 0, "inverse less than zero: " + a + " inv mod " + mod + " equals " + inv);
                    } catch (ArithmeticException) {
                        Assert.True(!one.Equals(BigMath.Gcd(a, mod)), "should have found inverse for " + a + " mod " + mod);
                    }
                }
            }
            for (int j = 1; j < 10; j++)
            {
                mod = bi2 + BigInteger.FromInt64(j);
                for (int i = 0; i < 20; i++)
                {
                    try {
                        a   = bi3 + (BigInteger.FromInt64(i));
                        inv = BigMath.ModInverse(a, mod);
                        Assert.True(one.Equals((a * inv) % mod), "bad inverse: " + a + " inv mod " + mod + " equals " + inv);
                        Assert.True(inv.CompareTo(mod) < 0, "inverse greater than modulo: " + a + " inv mod " + mod + " equals " + inv);
                        Assert.True(inv.CompareTo(BigInteger.Zero) >= 0, "inverse less than zero: " + a + " inv mod " + mod + " equals " + inv);
                    } catch (ArithmeticException) {
                        Assert.True(!one.Equals(BigMath.Gcd(a, mod)), "should have found inverse for " + a + " mod " + mod);
                    }
                }
            }
        }
コード例 #2
0
        public static BigDecimal Divide(BigDecimal dividend, BigDecimal divisor)
        {
            BigInteger p = dividend.UnscaledValue;
            BigInteger q = divisor.UnscaledValue;
            BigInteger gcd;             // greatest common divisor between 'p' and 'q'
            BigInteger quotient;
            BigInteger remainder;
            long       diffScale = (long)dividend.Scale - divisor.Scale;
            int        newScale;    // the new scale for final quotient
            int        k;           // number of factors "2" in 'q'
            int        l       = 0; // number of factors "5" in 'q'
            int        i       = 1;
            int        lastPow = BigDecimal.FivePow.Length - 1;

            if (divisor.IsZero)
            {
                // math.04=Division by zero
                throw new ArithmeticException(Messages.math04);                 //$NON-NLS-1$
            }
            if (p.Sign == 0)
            {
                return(BigDecimal.GetZeroScaledBy(diffScale));
            }
            // To divide both by the GCD
            gcd = BigMath.Gcd(p, q);
            p   = p / gcd;
            q   = q / gcd;
            // To simplify all "2" factors of q, dividing by 2^k
            k = q.LowestSetBit;
            q = q >> k;
            // To simplify all "5" factors of q, dividing by 5^l
            do
            {
                quotient = BigMath.DivideAndRemainder(q, BigDecimal.FivePow[i], out remainder);
                if (remainder.Sign == 0)
                {
                    l += i;
                    if (i < lastPow)
                    {
                        i++;
                    }
                    q = quotient;
                }
                else
                {
                    if (i == 1)
                    {
                        break;
                    }
                    i = 1;
                }
            } while (true);
            // If  abs(q) != 1  then the quotient is periodic
            if (!BigMath.Abs(q).Equals(BigInteger.One))
            {
                // math.05=Non-terminating decimal expansion; no exact representable decimal result.
                throw new ArithmeticException(Messages.math05);                 //$NON-NLS-1$
            }
            // The sign of the is fixed and the quotient will be saved in 'p'
            if (q.Sign < 0)
            {
                p = -p;
            }
            // Checking if the new scale is out of range
            newScale = BigDecimal.ToIntScale(diffScale + System.Math.Max(k, l));
            // k >= 0  and  l >= 0  implies that  k - l  is in the 32-bit range
            i = k - l;

            p = (i > 0)
                                ? Multiplication.MultiplyByFivePow(p, i)
                                : p << -i;
            return(new BigDecimal(p, newScale));
        }