public static BigDecimal DividePrimitiveLongs(long scaledDividend, long scaledDivisor, int scale, RoundingMode roundingMode) { long quotient = scaledDividend / scaledDivisor; long remainder = scaledDividend % scaledDivisor; int sign = System.Math.Sign(scaledDividend) * System.Math.Sign(scaledDivisor); if (remainder != 0) { // Checking if: remainder * 2 >= scaledDivisor int compRem; // 'compare to remainder' compRem = BigDecimal.LongCompareTo(System.Math.Abs(remainder) << 1, System.Math.Abs(scaledDivisor)); // To look if there is a carry quotient += BigDecimal.RoundingBehavior(((int)quotient) & 1, sign * (5 + compRem), roundingMode); } // Constructing the result with the appropriate unscaled value return(BigDecimal.Create(quotient, scale)); }
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)); }