/** * 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); } }
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 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 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)); }
/** * Returns this {@code BigDecimal} as a double value. If {@code this} is too * big to be represented as an float, then {@code Double.POSITIVE_INFINITY} * or {@code Double.NEGATIVE_INFINITY} is returned. * <p> * Note, that if the unscaled value has more than 53 significant digits, * then this decimal cannot be represented exactly in a double variable. In * this case the result is rounded. * <p> * For example, if the instance {@code x1 = new BigDecimal("0.1")} cannot be * represented exactly as a double, and thus {@code x1.equals(new * BigDecimal(x1.ToDouble())} returns {@code false} for this case. * <p> * Similarly, if the instance {@code new BigDecimal(9007199254740993L)} is * converted to a double, the result is {@code 9.007199254740992E15}. * <p> * * @return this {@code BigDecimal} as a double value. */ public double ToDouble() { int sign = Sign; int exponent = 1076; // bias + 53 int lowestSetBit; int discardedSize; long powerOfTwo = this._bitLength - (long)(_scale / Log10Of2); long bits; // IEEE-754 Standard long tempBits; // for temporal calculations BigInteger mantisa; if ((powerOfTwo < -1074) || (sign == 0)) { // Cases which 'this' is very small return(sign * 0.0d); } else if (powerOfTwo > 1025) { // Cases which 'this' is very large return(sign * Double.PositiveInfinity); } mantisa = BigMath.Abs(GetUnscaledValue()); // Let be: this = [u,s], with s > 0 if (_scale <= 0) { // mantisa = abs(u) * 10^s mantisa = mantisa * Multiplication.PowerOf10(-_scale); } else { // (scale > 0) BigInteger quotient; BigInteger remainder; BigInteger powerOfTen = Multiplication.PowerOf10(_scale); int k = 100 - (int)powerOfTwo; int compRem; if (k > 0) { /* Computing (mantisa * 2^k) , where 'k' is a enough big * power of '2' to can divide by 10^s */ mantisa = mantisa << k; exponent -= k; } // Computing (mantisa * 2^k) / 10^s quotient = BigMath.DivideAndRemainder(mantisa, powerOfTen, out remainder); // To check if the fractional part >= 0.5 compRem = remainder.ShiftLeftOneBit().CompareTo(powerOfTen); // To add two rounded bits at end of mantisa mantisa = (quotient << 2) + BigInteger.FromInt64((compRem * (compRem + 3)) / 2 + 1); exponent -= 2; } lowestSetBit = mantisa.LowestSetBit; discardedSize = mantisa.BitLength - 54; if (discardedSize > 0) { // (n > 54) // mantisa = (abs(u) * 10^s) >> (n - 54) bits = (mantisa >> discardedSize).ToInt64(); tempBits = bits; // #bits = 54, to check if the discarded fraction produces a carry if ((((bits & 1) == 1) && (lowestSetBit < discardedSize)) || ((bits & 3) == 3)) { bits += 2; } } else { // (n <= 54) // mantisa = (abs(u) * 10^s) << (54 - n) bits = mantisa.ToInt64() << -discardedSize; tempBits = bits; // #bits = 54, to check if the discarded fraction produces a carry: if ((bits & 3) == 3) { bits += 2; } } // Testing bit 54 to check if the carry creates a new binary digit if ((bits & 0x40000000000000L) == 0) { // To drop the last bit of mantisa (first discarded) bits >>= 1; // exponent = 2^(s-n+53+bias) exponent += discardedSize; } else { // #bits = 54 bits >>= 2; exponent += discardedSize + 1; } // To test if the 53-bits number fits in 'double' if (exponent > 2046) { // (exponent - bias > 1023) return(sign * Double.PositiveInfinity); } if (exponent <= 0) { // (exponent - bias <= -1023) // Denormalized numbers (having exponent == 0) if (exponent < -53) { // exponent - bias < -1076 return(sign * 0.0d); } // -1076 <= exponent - bias <= -1023 // To discard '- exponent + 1' bits bits = tempBits >> 1; tempBits = bits & Utils.URShift(-1L, (63 + exponent)); bits >>= (-exponent); // To test if after discard bits, a new carry is generated if (((bits & 3) == 3) || (((bits & 1) == 1) && (tempBits != 0) && (lowestSetBit < discardedSize))) { bits += 1; } exponent = 0; bits >>= 1; } // Construct the 64 double bits: [sign(1), exponent(11), mantisa(52)] // bits = (long)((ulong)sign & 0x8000000000000000L) | ((long)exponent << 52) | (bits & 0xFFFFFFFFFFFFFL); bits = sign & Int64.MinValue | ((long)exponent << 52) | (bits & 0xFFFFFFFFFFFFFL); return(BitConverter.Int64BitsToDouble(bits)); }
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))); }
public static BigDecimal Divide(BigDecimal dividend, BigDecimal divisor, MathContext mc) { /* Calculating how many zeros must be append to 'dividend' * to obtain a quotient with at least 'mc.precision()' digits */ long traillingZeros = mc.Precision + 2L + divisor.AproxPrecision() - dividend.AproxPrecision(); long diffScale = (long)dividend.Scale - divisor.Scale; long newScale = diffScale; // scale of the final quotient int compRem; // to compare the remainder int i = 1; // index int lastPow = BigDecimal.TenPow.Length - 1; // last power of ten BigInteger integerQuot; // for temporal results BigInteger quotient = dividend.UnscaledValue; BigInteger remainder; // In special cases it reduces the problem to call the dual method if ((mc.Precision == 0) || (dividend.IsZero) || (divisor.IsZero)) { return(Divide(dividend, divisor)); } if (traillingZeros > 0) { // To append trailing zeros at end of dividend quotient = dividend.UnscaledValue * Multiplication.PowerOf10(traillingZeros); newScale += traillingZeros; } quotient = BigMath.DivideAndRemainder(quotient, divisor.UnscaledValue, out remainder); integerQuot = quotient; // Calculating the exact quotient with at least 'mc.precision()' digits if (remainder.Sign != 0) { // Checking if: 2 * remainder >= divisor ? compRem = remainder.ShiftLeftOneBit().CompareTo(divisor.UnscaledValue); // quot := quot * 10 + r; with 'r' in {-6,-5,-4, 0,+4,+5,+6} integerQuot = (integerQuot * BigInteger.Ten) + BigInteger.FromInt64(quotient.Sign * (5 + compRem)); newScale++; } else { // To strip trailing zeros until the preferred scale is reached while (!BigInteger.TestBit(integerQuot, 0)) { quotient = BigMath.DivideAndRemainder(integerQuot, BigDecimal.TenPow[i], out remainder); if ((remainder.Sign == 0) && (newScale - i >= diffScale)) { newScale -= i; if (i < lastPow) { i++; } integerQuot = quotient; } else { if (i == 1) { break; } i = 1; } } } // To perform rounding return(new BigDecimal(integerQuot, BigDecimal.ToIntScale(newScale), mc)); }