package org.spaceroots.mantissa.algebra;

import java.io.Serializable;
import java.math.BigInteger;
/** This class implements reduced rational numbers.
 * 

Instances of this class are immutable.

* @version $Id: RationalNumber.java 1711 2006-12-13 21:27:51Z luc $ * @author L. Maisonobe */ public class RationalNumber implements Serializable { /** Zero as a rational numer. */ public static final RationalNumber ZERO = new RationalNumber(0l); /** One as a rational numer. */ public static final RationalNumber ONE = new RationalNumber(1l); /** Simple constructor. * Build a null rational number */ public RationalNumber() { p = BigInteger.ZERO; q = BigInteger.ONE; } /** Simple constructor. * Build a rational number from a numerator and a denominator. * @param numerator numerator of the rational number * @param denominator denominator of the rational number * @exception ArithmeticException if the denominator is zero */ public RationalNumber(long numerator, long denominator) { if (denominator == 0l) { throw new ArithmeticException("divide by zero"); } p = BigInteger.valueOf(numerator); q = BigInteger.valueOf(denominator); if (q.signum() < 0) { p = p.negate(); q = q.negate(); } simplify(); } /** Simple constructor. * Build a rational number from a numerator and a denominator. * @param numerator numerator of the rational number * @param denominator denominator of the rational number * @exception ArithmeticException if the denominator is zero */ public RationalNumber(BigInteger numerator, BigInteger denominator) { if (denominator.signum() == 0) { throw new ArithmeticException("divide by zero"); } p = numerator; q = denominator; if (q.signum() < 0) { p = p.negate(); q = q.negate(); } simplify(); } /** Simple constructor. * Build a rational number from a single integer * @param l value of the rational number */ public RationalNumber(long l) { p = BigInteger.valueOf(l); q = BigInteger.ONE; } /** Simple constructor. * Build a rational number from a single integer * @param i value of the rational number */ public RationalNumber(BigInteger i) { p = i; q = BigInteger.ONE; } /** Negate the instance. * @return a new rational number, opposite to the isntance */ public RationalNumber negate() { return new RationalNumber(p.negate(), q); } /** Add an integer to the instance. * @param l integer to add * @return a new rational number which is the sum of the instance and l */ public RationalNumber add(long l) { return add(BigInteger.valueOf(l)); } /** Add an integer to the instance. * @param l integer to add * @return a new rational number which is the sum of the instance and l */ public RationalNumber add(BigInteger l) { return new RationalNumber(p.add(q.multiply(l)), q); } /** Add a rational number to the instance. * @param r rational number to add * @return a new rational number which is the sum of the instance and r */ public RationalNumber add(RationalNumber r) { return new RationalNumber(p.multiply(r.q).add(r.p.multiply(q)), q.multiply(r.q)); } /** Subtract an integer from the instance. * @param l integer to subtract * @return a new rational number which is the difference the instance minus l */ public RationalNumber subtract(long l) { return subtract(BigInteger.valueOf(l)); } /** Subtract an integer from the instance. * @param l integer to subtract * @return a new rational number which is the difference the instance minus l */ public RationalNumber subtract(BigInteger l) { return new RationalNumber(p.subtract(q.multiply(l)), q); } /** Subtract a rational number from the instance. * @param r rational number to subtract * @return a new rational number which is the difference the instance minus r */ public RationalNumber subtract(RationalNumber r) { return new RationalNumber(p.multiply(r.q).subtract(r.p.multiply(q)), q.multiply(r.q)); } /** Multiply the instance by an integer. * @param l integer to multiply by * @return a new rational number which is the produc of the instance by l */ public RationalNumber multiply(long l) { return multiply(BigInteger.valueOf(l)); } /** Multiply the instance by an integer. * @param l integer to multiply by * @return a new rational number which is the produc of the instance by l */ public RationalNumber multiply(BigInteger l) { return new RationalNumber(p.multiply(l), q); } /** Multiply the instance by a rational number. * @param r rational number to multiply the instance with * @return a new rational number which is the product of the instance and r */ public RationalNumber multiply(RationalNumber r) { return new RationalNumber(p.multiply(r.p), q.multiply(r.q)); } /** Divide the instance by an integer. * @param l integer to divide by * @return a new rational number which is the quotient of the instance by l * @exception ArithmeticException if l is zero */ public RationalNumber divide(long l) { return divide(BigInteger.valueOf(l)); } /** Divide the instance by an integer. * @param l integer to divide by * @return a new rational number which is the quotient of the instance by l * @exception ArithmeticException if l is zero */ public RationalNumber divide(BigInteger l) { if (l.signum() == 0) { throw new ArithmeticException("divide by zero"); } if (l.signum() > 0) { return new RationalNumber(p, q.multiply(l)); } return new RationalNumber(p.negate(), q.multiply(l.negate())); } /** Divide the instance by a rational number. * @param r rational number to divide by * @return a new rational number which is the quotient of the instance by r * @exception ArithmeticException if r is zero */ public RationalNumber divide(RationalNumber r) { if (r.p.signum() == 0) { throw new ArithmeticException("divide by zero"); } BigInteger newP = p.multiply(r.q); BigInteger newQ = q.multiply(r.p); return (newQ.signum() < 0) ? new RationalNumber(newP.negate(), newQ.negate()) : new RationalNumber(newP, newQ); } /** Invert the instance. * @return the inverse of the instance * @exception ArithmeticException if the instance is zero */ public RationalNumber invert() { if (p.signum() == 0) { throw new ArithmeticException("divide by zero"); } return (q.signum() < 0) ? new RationalNumber(q.negate(), p.negate()) : new RationalNumber(q, p); } /** Simplify a rational number by removing common factors. */ private void simplify() { if (p.signum() == 0) { q = BigInteger.ONE; } else { BigInteger gcd = p.gcd(q); p = p.divide(gcd); q = q.divide(gcd); } } /** Get the numerator. * @return the signed numerator */ public BigInteger getNumerator() { return p; } /** Get the denominator. * @return the denominator (always positive) */ public BigInteger getDenominator() { return q; } /** Check if the number is zero. * @return true if the number is zero */ public boolean isZero() { return p.signum() == 0; } /** Check if the number is one. * @return true if the number is one */ public boolean isOne() { return (p.compareTo(BigInteger.ONE) == 0) && (q.compareTo(BigInteger.ONE) == 0); } /** Check if the number is integer. * @return true if the number is an integer */ public boolean isInteger() { return q.compareTo(BigInteger.ONE) == 0; } /** Check if the number is negative. * @return true if the number is negative */ public boolean isNegative() { return p.signum() < 0; } /** Get the absolute value of a rational number. * @param r rational number from which we want the absolute value * @return a new rational number which is the absolute value of r */ public static RationalNumber abs(RationalNumber r) { return new RationalNumber(r.p.abs(), r.q); } /** Return the double value of the instance. * @return the double value of the instance */ public double doubleValue() { BigInteger[] result = p.divideAndRemainder(q); return result[0].doubleValue() + (result[1].doubleValue() / q.doubleValue()); } /** Check if the instance is equal to another rational number. * Equality here is having the same value. * @return true if the object is a rational number which has the * same value as the instance */ public boolean equals(Object o) { if (o instanceof RationalNumber) { RationalNumber r = (RationalNumber) o; return (p.compareTo(r.p) == 0) && (q.compareTo(r.q) == 0); } return false; } /** Returns a hash code value for the object. * The hash code value is computed from the reduced numerator and * denominator, hence equal rational numbers have the same hash code, * as required by the method specification. * @return a hash code value for this object. */ public int hashCode() { return p.hashCode() ^ q.hashCode(); } /** Returns a string representation of the rational number. * The representation is reduced: there is no common factor left * between the numerator and the denominator. The '/' character and * the denominator are displayed only if the denominator is not * one. The sign is on the numerator. * @return string representation of the rational number */ public String toString() { return p + ((q.compareTo(BigInteger.ONE) == 0) ? "" : ("/" + q)); } /** Numerator. */ private BigInteger p; /** Denominator. */ private BigInteger q; private static final long serialVersionUID = -324954393137577531L; }

Ads help maintain this website.