/** * 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); }
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"); }
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)); }
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 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)); }
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"); }
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())); } }
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"); }
/** * 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); } }
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)); }
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"); }
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"); }
// 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); }
/** @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)); }
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)); }
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)); }
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)); }
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"); }
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"); }
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)); }
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); }
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)); }
/** * 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)); } }
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)); }
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"); }
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))); }
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)); }
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"); }
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"); }