Is there a commonly used rational numbers library in Java?
Does Apache Commons Math suit you?
Edit from Future: Please use Apache Commons or any other supported library. This was just a sample demonstration.
I implemented a small class that can be used for that purposes, maybe it can be useful for you as well, use with caution.
import java.util.ArrayList;
public class RationalNumber {
/**
*
* @author Suat KARAKUSOGLU
* @email [email protected]
* This class has 2 kind of constructors
* 1. is RationalNumber a=new RationalNumber("3.3");
* RationalNumber a=new RationalNumber("-3.3");
* With this constructor one can enter the decimal number and also specify whether negative or not
*
* 2. is RationalNumber a=new RationalNumber(3,5);
* With this constructor the first value is nominator and second one is denominator.
*
* The advantage side of this class is, it prevents the fractional errors while dividing
* RationalNumber keeps all denominator and nominator values as it is and when the real value is
* needed, the calculation occurs at that time.
*
* Supports multiply,divide,add,subtract operations on RationalNumber classes.
*
*/
/*
* Simple Usage:
*
* RationalNumber a=new RationalNumber("3.3");
* RationalNumber b=new RationalNumber("4.5");
* System.out.println("a ="+a.getStringValue());
* System.out.println("b ="+b.getStringValue());
* System.out.println("a-b ="+a.subtract(b).getStringValue());
* System.out.println("a ="+a.getStringValue());
* System.out.println("b ="+b.getStringValue());
* RationalNumber k=a.divide(b);
* System.out.println("a/b="+k.getStringValue());
* System.out.println("a/b="+k.getDoubleValue());
*
* System out results:
*
* a =33/10
* b =9/2
* a-b =-6/5
* a =33/10
* b =9/2
* a/b=11/15
* a/b=0.7333333333333333
*
*/
public ArrayList<Long> nominators = new ArrayList<Long>();
public ArrayList<Long> denominators = new ArrayList<Long>();
public RationalNumber(String rationalNumberStringValue) {
this(parseRationalNumberStringValue(rationalNumberStringValue)[0],
parseRationalNumberStringValue(rationalNumberStringValue)[1]);
}
private static Long[] parseRationalNumberStringValue(
String rationalNumberStringValue) {
boolean positive = true;
if (rationalNumberStringValue.charAt(0) == '-') {
positive = false;
rationalNumberStringValue = rationalNumberStringValue.substring(1);
}
// 0. index is keeping nominator
// 1. index is keeping denominator
Long[] nominatorDenominator = new Long[2];
nominatorDenominator[0] = 1l;
nominatorDenominator[1] = 1l;
String[] splittedNumberArr = rationalNumberStringValue.split("\\.");
String denominatorStr = splittedNumberArr[1];
for (int i = 0; i < denominatorStr.length(); i++) {
nominatorDenominator[1] *= 10;
}
rationalNumberStringValue = removeCharAt(rationalNumberStringValue,
rationalNumberStringValue.indexOf('.'));
nominatorDenominator[0] = Long.valueOf(rationalNumberStringValue);
if (!positive) {
nominatorDenominator[0] *= -1;
}
return nominatorDenominator;
}
public static String removeCharAt(String s, int pos) {
return s.substring(0, pos) + s.substring(pos + 1);
}
public RationalNumber(Integer nominator, Integer denominator) {
this((long) nominator, (long) denominator);
}
public RationalNumber(Long nominator, Long denominator) {
nominators.add(nominator);
denominators.add(denominator);
simplify();
}
public RationalNumber(ArrayList<Long> nominatorList,
ArrayList<Long> denominatorList) {
nominators.addAll(nominatorList);
denominators.addAll(denominatorList);
simplify();
}
public String getStringValue() {
return getMultipliedValue(this.nominators) + "/"
+ getMultipliedValue(this.denominators);
}
public double getDoubleValue() {
return (double) getMultipliedValue(this.nominators)
/ (double) getMultipliedValue(this.denominators);
}
public RationalNumber multiply(RationalNumber rationalNumberToMultiply) {
RationalNumber mulResult = new RationalNumber(
rationalNumberToMultiply.nominators,
rationalNumberToMultiply.denominators);
mulResult.nominators.addAll(this.nominators);
mulResult.denominators.addAll(this.denominators);
return RationalNumber.simplifyRationalNumber(mulResult);
}
public RationalNumber divide(RationalNumber rationalNumberToDivide) {
RationalNumber divideResult = new RationalNumber(
rationalNumberToDivide.nominators,
rationalNumberToDivide.denominators);
// division means multiplication with reverse values
ArrayList<Long> tempLongList = divideResult.nominators;
divideResult.nominators = divideResult.denominators;
divideResult.denominators = tempLongList;
return this.multiply(divideResult);
}
public RationalNumber add(RationalNumber rationalNumberToAdd) {
rationalNumberToAdd = RationalNumber
.simplifyRationalNumber(rationalNumberToAdd);
return new RationalNumber(
(getMultipliedValue(this.nominators) * getMultipliedValue(rationalNumberToAdd.denominators))
+ (getMultipliedValue(this.denominators) * getMultipliedValue(rationalNumberToAdd.nominators)),
(getMultipliedValue(this.denominators) * getMultipliedValue(rationalNumberToAdd.denominators)));
}
public RationalNumber subtract(RationalNumber rationalNumberToSubtract) {
rationalNumberToSubtract = RationalNumber
.simplifyRationalNumber(rationalNumberToSubtract);
RationalNumber subtractTempRational = new RationalNumber(
rationalNumberToSubtract.nominators,
rationalNumberToSubtract.denominators);
// Multiply one of its nominators negative value
subtractTempRational.nominators.set(0,
(subtractTempRational.nominators.get(0) * -1));
// add with its negative value
return this.add(subtractTempRational);
}
private long getMultipliedValue(ArrayList<Long> longList) {
Long mulResult = 1l;
for (Long tempLong : longList) {
mulResult *= tempLong;
}
return mulResult;
}
// simplifies original rationalnumber
public void simplify() {
long tempGcd = 1;
long iValue = 1;
long jValue = 1;
for (int i = 0; i < this.nominators.size(); i++) {
iValue = this.nominators.get(i);
for (int j = 0; j < this.denominators.size(); j++) {
jValue = this.denominators.get(j);
tempGcd = gcd(iValue, jValue);
this.nominators.set(i, iValue / tempGcd);
this.denominators.set(j, jValue / tempGcd);
}
}
}
public static RationalNumber simplifyRationalNumber(
RationalNumber rationalNumberToSimplify) {
long tempGcd = 1;
long iValue = 1;
long jValue = 1;
for (int i = 0; i < rationalNumberToSimplify.nominators.size(); i++) {
for (int j = 0; j < rationalNumberToSimplify.denominators.size(); j++) {
iValue = rationalNumberToSimplify.nominators.get(i);
jValue = rationalNumberToSimplify.denominators.get(j);
tempGcd = gcd(iValue, jValue);
rationalNumberToSimplify.nominators.set(i, iValue / tempGcd);
rationalNumberToSimplify.denominators.set(j, jValue / tempGcd);
}
}
return rationalNumberToSimplify;
}
// Euclidean algorithm to find greatest common divisor
public static long gcd(long a, long b) {
a = Math.abs(a);
b = Math.abs(b);
if (a < b) {
long temp = a;
a = b;
b = temp;
}
if (b == 0)
return a;
else
return gcd(b, a % b);
}
public RationalNumber add(int integerToAdd) {
RationalNumber tempRationalNumber=new RationalNumber(integerToAdd,1);
return this.add(tempRationalNumber);
}
public RationalNumber subtract(int integerToSubtract) {
RationalNumber tempRationalNumber=new RationalNumber(integerToSubtract,1);
return this.subtract(tempRationalNumber);
}
public RationalNumber multiply(int integerToMultiply) {
RationalNumber tempRationalNumber=new RationalNumber(integerToMultiply,1);
return this.multiply(tempRationalNumber);
}
public RationalNumber divide(int integerToDivide) {
RationalNumber tempRationalNumber=new RationalNumber(integerToDivide,1);
return this.divide(tempRationalNumber);
}
}
The JScience
library includes the class org.jscience.mathematics.number.Rational
. In addition to the usual factories, accessors and operations, one can construct other useful entities, including Polynomial<Rational>
, Vector<Rational>
and Matrix<Rational>
.
As an example, a function to obtain the lowest common denominator of a collection of fractions might look like this:
private static LargeInteger lcd(Collection<Rational> fractions) {
Rational sum = Rational.ZERO;
for (Rational rational : fractions) {
sum = sum.plus(rational);
}
return sum.getDivisor();
}
The following statement prints 6
:
System.out.println(lcd(Arrays.asList(
Rational.valueOf(1, 2), Rational.valueOf(1, 3))));
I'm not sure how commonly used it is, but the apfloat packages (Java and C++) contain a class for rational arithmetic.