/** * Divide the value of this fraction by another. * * @param fraction the fraction to divide by, must not be {@code null} * @return a {@code Fraction} instance with the resulting values * @throws IllegalArgumentException if the fraction is {@code null} * @throws MathArithmeticException if the fraction to divide by is zero * @throws MathArithmeticException if the resulting numerator or denominator exceeds {@code * Integer.MAX_VALUE} */ public Fraction divide(Fraction fraction) { if (fraction == null) { throw new NullArgumentException(LocalizedFormats.FRACTION); } if (fraction.numerator == 0) { throw new MathArithmeticException( LocalizedFormats.ZERO_FRACTION_TO_DIVIDE_BY, fraction.numerator, fraction.denominator); } return multiply(fraction.reciprocal()); }
/** * Implement add and subtract using algorithm described in Knuth 4.5.1. * * @param fraction the fraction to subtract, must not be {@code null} * @param isAdd true to add, false to subtract * @return a {@code Fraction} instance with the resulting values * @throws NullArgumentException if the fraction is {@code null} * @throws MathArithmeticException if the resulting numerator or denominator cannot be represented * in an {@code int}. */ private Fraction addSub(Fraction fraction, boolean isAdd) { if (fraction == null) { throw new NullArgumentException(LocalizedFormats.FRACTION); } // zero is identity for addition. if (numerator == 0) { return isAdd ? fraction : fraction.negate(); } if (fraction.numerator == 0) { return this; } // if denominators are randomly distributed, d1 will be 1 about 61% // of the time. int d1 = ArithmeticUtils.gcd(denominator, fraction.denominator); if (d1 == 1) { // result is ( (u*v' +/- u'v) / u'v') int uvp = ArithmeticUtils.mulAndCheck(numerator, fraction.denominator); int upv = ArithmeticUtils.mulAndCheck(fraction.numerator, denominator); return new Fraction( isAdd ? ArithmeticUtils.addAndCheck(uvp, upv) : ArithmeticUtils.subAndCheck(uvp, upv), ArithmeticUtils.mulAndCheck(denominator, fraction.denominator)); } // the quantity 't' requires 65 bits of precision; see knuth 4.5.1 // exercise 7. we're going to use a BigInteger. // t = u(v'/d1) +/- v(u'/d1) BigInteger uvp = BigInteger.valueOf(numerator).multiply(BigInteger.valueOf(fraction.denominator / d1)); BigInteger upv = BigInteger.valueOf(fraction.numerator).multiply(BigInteger.valueOf(denominator / d1)); BigInteger t = isAdd ? uvp.add(upv) : uvp.subtract(upv); // but d2 doesn't need extra precision because // d2 = gcd(t,d1) = gcd(t mod d1, d1) int tmodd1 = t.mod(BigInteger.valueOf(d1)).intValue(); int d2 = (tmodd1 == 0) ? d1 : ArithmeticUtils.gcd(tmodd1, d1); // result is (t/d2) / (u'/d1)(v'/d2) BigInteger w = t.divide(BigInteger.valueOf(d2)); if (w.bitLength() > 31) { throw new MathArithmeticException(LocalizedFormats.NUMERATOR_OVERFLOW_AFTER_MULTIPLY, w); } return new Fraction( w.intValue(), ArithmeticUtils.mulAndCheck(denominator / d1, fraction.denominator / d2)); }