/** * Returns a new {@code BigDecimal} whose value is {@code this * * multiplicand}. The scale of the result is the sum of the scales of the * two arguments. * * @param multiplicand * value to be multiplied with {@code this}. * @return {@code this * multiplicand}. * @throws NullPointerException * if {@code multiplicand == null}. */ public static BigDecimal Multiply(BigDecimal value, BigDecimal multiplicand) { long newScale = (long)value.Scale + multiplicand.Scale; if ((value.IsZero) || (multiplicand.IsZero)) { return(BigDecimal.GetZeroScaledBy(newScale)); } /* Let be: this = [u1,s1] and multiplicand = [u2,s2] so: * this x multiplicand = [ s1 * s2 , s1 + s2 ] */ if (value.BitLength + multiplicand.BitLength < 64) { return(BigDecimal.Create(value.SmallValue * multiplicand.SmallValue, BigDecimal.ToIntScale(newScale))); } return(new BigDecimal(value.UnscaledValue * multiplicand.UnscaledValue, BigDecimal.ToIntScale(newScale))); }
/** * Returns a new {@code BigDecimal} whose value is {@code this} 10^{@code n}. * The scale of the result is {@code this.scale()} - {@code n}. * The precision of the result is the precision of {@code this}. * <p> * This method has the same effect as {@link #movePointRight}, except that * the precision is not changed. * * @param n * number of places the decimal point has to be moved. * @return {@code this * 10^n} */ public static BigDecimal ScaleByPowerOfTen(BigDecimal number, int n) { long newScale = number.Scale - (long)n; if (number.BitLength < 64) { //Taking care when a 0 is to be scaled if (number.SmallValue == 0) { return(BigDecimal.GetZeroScaledBy(newScale)); } return(BigDecimal.Create(number.SmallValue, BigDecimal.ToIntScale(newScale))); } return(new BigDecimal(number.UnscaledValue, BigDecimal.ToIntScale(newScale))); }
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 MovePoint(BigDecimal number, long newScale) { if (number.IsZero) { return(BigDecimal.GetZeroScaledBy(System.Math.Max(newScale, 0))); } /* When: 'n'== Integer.MIN_VALUE isn't possible to call to movePointRight(-n) * since -Integer.MIN_VALUE == Integer.MIN_VALUE */ if (newScale >= 0) { if (number.BitLength < 64) { return(BigDecimal.Create(number.SmallValue, BigDecimal.ToIntScale(newScale))); } return(new BigDecimal(number.UnscaledValue, BigDecimal.ToIntScale(newScale))); } if (-newScale < BigDecimal.LongTenPow.Length && number.BitLength + BigDecimal.LongTenPowBitLength[(int)-newScale] < 64) { return(BigDecimal.Create(number.SmallValue * BigDecimal.LongTenPow[(int)-newScale], 0)); } return(new BigDecimal(Multiplication.MultiplyByTenPow(number.UnscaledValue, (int)-newScale), 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)); }
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); }
public static BigDecimal DivideToIntegralValue(BigDecimal dividend, BigDecimal divisor) { BigInteger integralValue; // the integer of result BigInteger powerOfTen; // some power of ten BigInteger quotient; BigInteger remainder; long newScale = (long)dividend.Scale - divisor.Scale; long tempScale = 0; int i = 1; int lastPow = BigDecimal.TenPow.Length - 1; if (divisor.IsZero) { // math.04=Division by zero throw new ArithmeticException(Messages.math04); //$NON-NLS-1$ } if ((divisor.AproxPrecision() + newScale > dividend.AproxPrecision() + 1L) || (dividend.IsZero)) { /* If the divisor's integer part is greater than this's integer part, * the result must be zero with the appropriate scale */ integralValue = BigInteger.Zero; } else if (newScale == 0) { integralValue = dividend.UnscaledValue / divisor.UnscaledValue; } else if (newScale > 0) { powerOfTen = Multiplication.PowerOf10(newScale); integralValue = dividend.UnscaledValue / (divisor.UnscaledValue * powerOfTen); integralValue = integralValue * powerOfTen; } else { // (newScale < 0) powerOfTen = Multiplication.PowerOf10(-newScale); integralValue = (dividend.UnscaledValue * powerOfTen) / divisor.UnscaledValue; // To strip trailing zeros approximating to the preferred scale while (!BigInteger.TestBit(integralValue, 0)) { quotient = BigMath.DivideAndRemainder(integralValue, BigDecimal.TenPow[i], out remainder); if ((remainder.Sign == 0) && (tempScale - i >= newScale)) { tempScale -= i; if (i < lastPow) { i++; } integralValue = quotient; } else { if (i == 1) { break; } i = 1; } } newScale = tempScale; } return((integralValue.Sign == 0) ? BigDecimal.GetZeroScaledBy(newScale) : new BigDecimal(integralValue, BigDecimal.ToIntScale(newScale))); }