Created
March 4, 2017 18:36
-
-
Save FlorianCassayre/b12544a450ee67b3c142cb6562a3cb1e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.math.BigInteger; | |
public final class BigRational extends Number implements Comparable<BigRational> | |
{ | |
public final static BigRational ZERO = valueOf(0); | |
public final static BigRational ONE = valueOf(1); | |
public final static BigRational MINUS_ONE = valueOf(-1); | |
private BigInteger numerator; | |
private BigInteger denominator; | |
public BigRational(BigInteger numerator, BigInteger denominator) | |
{ | |
if(denominator.equals(BigInteger.ZERO)) | |
throw new ArithmeticException(); | |
this.numerator = numerator; | |
this.denominator = denominator; | |
reduce(); | |
} | |
public BigRational(BigInteger numerator) | |
{ | |
this(numerator, BigInteger.ONE); | |
} | |
public BigRational() | |
{ | |
this(BigInteger.ZERO); | |
} | |
private void reduce() | |
{ | |
boolean sign = false; | |
if(numerator.signum() >= 0 ^ denominator.signum() >= 0) | |
{ | |
sign = true; | |
} | |
else | |
{ | |
if(numerator.equals(BigInteger.ZERO)) | |
{ | |
denominator = BigInteger.ONE; | |
} | |
} | |
numerator = numerator.abs(); | |
denominator = denominator.abs(); | |
if(sign) | |
{ | |
numerator = numerator.multiply(BigInteger.valueOf(-1)); | |
} | |
final BigInteger divisor = pgcd(numerator.abs(), denominator); | |
if(!divisor.equals(BigInteger.ONE)) | |
{ | |
numerator = numerator.divide(divisor); | |
denominator = denominator.divide(divisor); | |
} | |
} | |
@Override | |
public int intValue() | |
{ | |
return numerator.intValue() / denominator.intValue(); | |
} | |
@Override | |
public long longValue() | |
{ | |
return numerator.longValue() / denominator.longValue(); | |
} | |
@Override | |
public float floatValue() | |
{ | |
return numerator.floatValue() / denominator.floatValue(); | |
} | |
@Override | |
public double doubleValue() | |
{ | |
return numerator.doubleValue() / denominator.doubleValue(); | |
} | |
public static BigRational valueOf(long num, long denom) | |
{ | |
return new BigRational(BigInteger.valueOf(num), BigInteger.valueOf(denom)); | |
} | |
public static BigRational valueOf(long num) | |
{ | |
return valueOf(num, 1); | |
} | |
public BigInteger getNumerator() | |
{ | |
return numerator; | |
} | |
public BigInteger getDenominator() | |
{ | |
return denominator; | |
} | |
public BigRational add(BigRational n) | |
{ | |
BigInteger num1 = numerator, denom1 = denominator, num2 = n.numerator, denom2 = n.denominator; | |
num1 = num1.multiply(denom2); | |
num2 = num2.multiply(denom1); | |
BigInteger denom = denom1.multiply(denom2); | |
return new BigRational(num1.add(num2), denom); | |
} | |
public BigRational substract(BigRational n) | |
{ | |
return add(new BigRational(n.numerator.multiply(BigInteger.valueOf(-1)), n.denominator)); | |
} | |
public BigRational multiply(BigRational n) | |
{ | |
BigInteger num1 = numerator, denom1 = denominator, num2 = n.numerator, denom2 = n.denominator; | |
num1 = num1.multiply(num2); | |
denom1 = denom1.multiply(denom2); | |
return new BigRational(num1, denom1); | |
} | |
public BigRational divide(BigRational n) | |
{ | |
return multiply(new BigRational(n.denominator, n.numerator)); | |
} | |
public BigRational reciprocal() | |
{ | |
return ONE.divide(this); | |
} | |
public boolean isInteger() | |
{ | |
return denominator.equals(BigInteger.ONE); | |
} | |
public boolean isOne() | |
{ | |
return numerator.equals(denominator); | |
} | |
public BigRational abs() | |
{ | |
return new BigRational(numerator.abs(), denominator); | |
} | |
public BigRational pow(int n) | |
{ | |
BigRational b = ONE; | |
for(int i = 0; i < n; i++) | |
{ | |
b = b.multiply(this); | |
} | |
return b; | |
} | |
private BigInteger pgcd(BigInteger a, BigInteger b) | |
{ | |
BigInteger r; | |
while(!b.equals(BigInteger.ZERO)) | |
{ | |
r = a.mod(b); | |
a = b; | |
b = r; | |
} | |
return a; | |
} | |
@Override | |
public String toString() | |
{ | |
return numerator.toString() + "/" + denominator.toString(); | |
} | |
@Override | |
public int hashCode() | |
{ | |
return toString().hashCode(); // Since there is one unique string representation, this should be unique too. | |
} | |
@Override | |
public boolean equals(Object object) | |
{ | |
if(object instanceof BigRational) | |
{ | |
BigRational n = (BigRational) object; | |
if(numerator.equals(n.numerator) && denominator.equals(n.denominator)) | |
return true; | |
} | |
return false; | |
} | |
@Override | |
public int compareTo(BigRational o) | |
{ | |
BigInteger a = numerator.multiply(o.denominator); | |
BigInteger b = denominator.multiply(o.numerator); | |
return a.compareTo(b); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment