private static BigDecimal divideBigIntegers(BigInteger scaledDividend, BigInteger scaledDivisor, int scale, RoundingMode roundingMode) { BigInteger[] quotAndRem = scaledDividend.divideAndRemainder(scaledDivisor); // quotient and remainder // If after division there is a remainder... BigInteger quotient = quotAndRem[0]; BigInteger remainder = quotAndRem[1]; if (remainder.signum() == 0) { return new BigDecimal(quotient, scale); } int sign = scaledDividend.signum() * scaledDivisor.signum(); int compRem; // 'compare to remainder' if(scaledDivisor.bitLength() < 63) { // 63 in order to avoid out of long after <<1 long rem = remainder.longValue(); long divisor = scaledDivisor.longValue(); compRem = longCompareTo(Math.Abs(rem) << 1,Math.Abs(divisor)); // To look if there is a carry compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0, sign * (5 + compRem), roundingMode); } else { // Checking if: remainder * 2 >= scaledDivisor compRem = remainder.abs().shiftLeftOneBit().compareTo(scaledDivisor.abs()); compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0, sign * (5 + compRem), roundingMode); } if (compRem != 0) { if(quotient.bitLength() < 63) { return valueOf(quotient.longValue() + compRem,scale); } quotient = quotient.add(BigInteger.valueOf(compRem)); return new BigDecimal(quotient, scale); } // Constructing the result with the appropriate unscaled value return new BigDecimal(quotient, scale); }