Here is a class to handle fractions with Java using BigInteger because it supports gcd calculus. I don't know if BigInteger is the optimal use with fractions, but this is an alternative with fractions. This class supports the most common fractional operations. It's a pity Java doesn't support the operators overloading like C++. The code:
import java.math.BigInteger;
import java.util.regex.Pattern;
public class Rational {
private BigInteger numerator;
private BigInteger denominator;
private static final BigInteger ZERO = new BigInteger("0");
private static final BigInteger ONE = new BigInteger("1");
private void normalize(){
BigInteger the_gcd = numerator.gcd(denominator);
if(the_gcd.signum() == -1) the_gcd = the_gcd.abs();
if(numerator.signum() == -1 && denominator.signum() == -1){
numerator = numerator.abs();
denominator = denominator.abs();
}
numerator = numerator.divide(the_gcd);
denominator = denominator.divide(the_gcd);
}
public Rational opposite(){
return new Rational(this.numerator.negate(), this.denominator);
}
public Rational absolute() {
if(this.numerator.signum() == 1 && this.denominator.signum() == 1) return this;
else return this.opposite();
}
public Rational(BigInteger numerator, BigInteger denominator) {
if(denominator.signum() == 0)
throw new IllegalArgumentException("The denominator can't be ZERO.");
this.numerator = numerator;
this.denominator = denominator;
normalize();
}
public Rational(String fraction){
fraction = fraction.replaceAll(" ","");
if(!fraction.contains("/")){
this.numerator = new BigInteger(fraction);
this.denominator = BigInteger.ONE;
}
else {
String[] fraction1 = fraction.split(Pattern.quote("/"));
if(fraction1[1].equals("0"))
throw new IllegalArgumentException("The denominator can't be ZERO.");
this.numerator = new BigInteger(fraction1[0]);
this.denominator = new BigInteger(fraction1[1]);
}
normalize();
}
public Rational add(Rational q) {
BigInteger product = this.denominator.multiply(q.denominator);
BigInteger the_mcm = product.divide(this.denominator.gcd(q.denominator));
BigInteger n = (the_mcm.divide(this.denominator)).multiply(this.numerator);
n = n.add((the_mcm.divide(q.denominator)).multiply(q.numerator));
return new Rational(n, the_mcm);
}
public Rational subtract(Rational q){
return this.add(q.opposite());
}
public Rational product(Rational q){
return new Rational(this.numerator.multiply(q.numerator), this.denominator.multiply(q.denominator));
}
public Rational divide(Rational q){
if(q.denominator.signum() == 0) throw new ArithmeticException("Divided by ZERO is illegal.");
return new Rational(this.numerator.multiply(q.denominator), this.denominator.multiply(q.numerator));
}
public int mod(){
return this.numerator.intValue() % this.denominator.intValue();
}
public Rational inverse(){
if(this.numerator.signum() == 0) throw new ArithmeticException("Not exist the inverse when the numerator is ZERO.");
return new Rational(this.denominator, this.numerator);
}
public Rational pow(int n){
return new Rational(this.numerator.pow(n), this.denominator.pow(n));
}
public double toReal(){
if(this.denominator.equals(ZERO)) throw new ArithmeticException("It's not a number, NAN");
return this.numerator.doubleValue() / this.denominator.doubleValue();
}
public String compares(Rational q){
BigInteger expression1 = this.numerator.multiply(q.denominator);
BigInteger expression2 = this.denominator.multiply(numerator);
BigInteger expression = expression1.subtract(expression2);
if(expression.signum() == -1) return this.toString() + " > " + q.toString();
else if(expression.signum() == 1) return this.toString() + " < " + q.toString();
else return this.toString() + " = " + q.toString();
}
public Rational simplify(){
normalize();
return new Rational(this.numerator, this.denominator);
}
@Override
public String toString() {
if(numerator.equals(ZERO) && ! denominator.equals(ZERO))
return "0";
if(denominator.equals(ONE)) return "" + numerator;
else if((numerator.signum() == -1 && denominator.signum() == -1) ||
(numerator.signum() == 1 && denominator.signum() == -1))
return numerator.negate() + " / " + denominator.negate();
else return numerator + " / " + denominator;
}
}
The class contains 2 different constructors, sum, subtract, product, division, opposite, inverse, simplify... Here's a short main code to practice:
import java.math.BigInteger;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
Rational p = new Rational(new BigInteger("1"), new BigInteger("-2"));
Rational q = new Rational(new BigInteger("3"), new BigInteger("4"));
Rational p_plus_q = p.add(q);
Rational p_prod_q = p.product(q);
Rational p_div_q = p.divide(q);
Rational p_minus_q = p.subtract(q);
System.out.println(p_plus_q);
System.out.println(p_minus_q);
System.out.println(p_prod_q);
System.out.println(p_div_q);
System.out.println(p.absolute());
System.out.println(p.compares(q));
Rational r = new Rational(new BigInteger("-4"), new BigInteger("6"));
System.out.println(r.simplify());
System.out.println(r.pow(2));
System.out.println(r.inverse());
System.out.println(r.toReal());
System.out.println(r.mod());
Rational q1 = new Rational("-8/5");
Rational q2 = new Rational("3 / 4");
Rational q3 = new Rational("2");
System.out.println("WITH CHARACTERS");
System.out.println("===============");
System.out.println(q1.product(q2));
System.out.println(q1.product(q3));
}
}