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"); } }
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)); }
// 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); }
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); }
/** * @param m a positive modulus * Return the greatest common divisor of op1 and op2, * * @param op1 * must be greater than zero * @param op2 * must be greater than zero * @see BigInteger#gcd(BigInteger) * @return {@code GCD(op1, op2)} */ public static BigInteger GcdBinary(BigInteger op1, BigInteger op2) { // PRE: (op1 > 0) and (op2 > 0) /* * Divide both number the maximal possible times by 2 without rounding * gcd(2*a, 2*b) = 2 * gcd(a,b) */ int lsb1 = op1.LowestSetBit; int lsb2 = op2.LowestSetBit; int pow2Count = System.Math.Min(lsb1, lsb2); BitLevel.InplaceShiftRight(op1, lsb1); BitLevel.InplaceShiftRight(op2, lsb2); BigInteger swap; // I want op2 > op1 if (op1.CompareTo(op2) == BigInteger.GREATER) { swap = op1; op1 = op2; op2 = swap; } do { // INV: op2 >= op1 && both are odd unless op1 = 0 // Optimization for small operands // (op2.bitLength() < 64) implies by INV (op1.bitLength() < 64) if ((op2.numberLength == 1) || ((op2.numberLength == 2) && (op2.Digits[1] > 0))) { op2 = BigInteger.FromInt64(Division.GcdBinary(op1.ToInt64(), op2.ToInt64())); break; } // Implements one step of the Euclidean algorithm // To reduce one operand if it's much smaller than the other one if (op2.numberLength > op1.numberLength * 1.2) { op2 = BigMath.Remainder(op2, op1); if (op2.Sign != 0) { BitLevel.InplaceShiftRight(op2, op2.LowestSetBit); } } else { // Use Knuth's algorithm of successive subtract and shifting do { Elementary.inplaceSubtract(op2, op1); // both are odd BitLevel.InplaceShiftRight(op2, op2.LowestSetBit); // op2 is even } while (op2.CompareTo(op1) >= BigInteger.EQUALS); } // now op1 >= op2 swap = op2; op2 = op1; op1 = swap; } while (op1.Sign != 0); return(op2 << pow2Count); }