Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * @(#)Rational.java  
   * 
   * Copyright (c) 2009-2011 Werner Randelshofer, Goldau, Switzerland.
   * All rights reserved.
   *
   * You may not use, copy or modify this file, except in compliance with the
   * license agreement you entered into with Werner Randelshofer.
   * For details see accompanying license terms.
  */
 package org.monte.media.math;
 
 import static java.lang.Math.*;
 import static org.monte.media.math.IntMath.*;

Represents a TIFF RATIONAL number.

Two LONGs 32-bit (4-byte) unsigned integer: the first represents the numerator of a fraction; the second, the denominator.

Invariants:

  • denominator>=0, the denominator is always a positive integer
  • 0/1 is the unique representation of 0.
  • 1/0,-1/0 are the unique representations of infinity.

Author(s):
Werner Randelshofer
Version:
$Id: Rational.java 299 2013-01-03 07:40:18Z werner $
 
 public class Rational extends Number {
 
     public static final Rational ONE = new Rational(1, 1,false);
     public static final Rational ZERO = new Rational(0, 1,false);
     public static final long serialVersionUID = 1L;
     private final long num;
     private final long den;
 
     public Rational(long numerator) {
         this(numerator, 1);
     }
 
     public Rational(long numeratorlong denominator) {
         this(numeratordenominatortrue);
     }
 
     private Rational(long numeratorlong denominatorboolean reduceFraction) {
         if (numerator == 0) {
             // Invariant: 0/1 is unique representation of 0
             denominator = 1;
         }
 
         if (denominator == 0) {
             // Invariant: 1/0, -1/0 are unique representations of infinity
             numerator = (numerator > 0) ? 1 : -1;
         } else if (denominator < 0) {
             // Invariant: denominator is always positive
             denominator = -denominator;
             numerator = -numerator;
         }
 
         if (reduceFraction) {
             long g = gcd(numeratordenominator);
              = numerator / g;
              = denominator / g;
         } else {
              = numerator;
              = denominator;
         }
     }
 
     private Rational(BigInteger numeratorBigInteger denominatorboolean reduceFraction) {
         if (numerator.equals(.)) {
             // Invariant: 0/1 is unique representation of 0
             denominator = .;
         }
 
         if (denominator.equals(.)) {
             // Invariant: 1/0, -1/0 are unique representations of infinity
             numerator = (numerator.compareTo(.) > 0) ? . : ..negate();
         } else if (denominator.compareTo(.) < 0) {
             // Invariant: denominator is always positive
             denominator = denominator.negate();
             numerator = numerator.negate();
         }
 
         BigInteger numBdenB;
         if (reduceFraction) {
             BigInteger g = gcd(numeratordenominator);
             numB = numerator.divide(g);
             denB = denominator.divide(g);
         } else {
             numB = numerator;
             denB = denominator;
         }
         int bitLength = Math.max(numB.bitLength(), denB.bitLength());
         if (bitLength > 63) {
             numB = numB.shiftRight(bitLength - 63);
             denB = denB.shiftRight(bitLength - 63);
             if (numB.equals(.)) {
                 // Invariant: 0/1 is unique representation of 0
                 denB = .;
            }
            if (denB.equals(.)) {
                // Invariant: 1/0, -1/0 are unique representations of infinity
                numB = (numB.compareTo(.) > 0) ? . : ..negate();
            }
        }
         = numB.longValue();
         = denB.longValue();
    }
    public Rational(Rational r) {
        this(r.numr.den);
    }
    public long getNumerator() {
        return ;
    }
    public long getDenominator() {
        return ;
    }
    public Rational add(Rational that) {
        return add(thattrue);
    }
    private Rational add(Rational thatboolean reduceFraction) {
        if (this. == that.den) {
            // => same denominator: add numerators 
            return new Rational(this. + that.numthis.reduceFraction);
        }
        // FIXME - handle overflow
        long s = scm(this.that.den);
        Rational result = new Rational(
                this. * (s / this.) + that.num * (s / that.den),
                sreduceFraction);
        return result;
    }

    
Warning. Rational is supposed to be immutable. * private Rational addAssign(Rational that) { if (this.den == that.den) { // => same denominator: add numerators this.num += that.num; return this; } // FIXME - handle overflow long s = scm(this.den, that.den); this.num = this.num * (s / this.den) + that.num * (s / that.den); this.den = s; return reduceAssign(); }
    public Rational subtract(Rational that) {
        return add(that.negate());
    }
    public Rational negate() {
        return valueOf(-);
    }
    public Rational inverse() {
        return valueOf(false);
    }

    
Returns the closest rational with the specified denominator which is smaller or equal than this number.
    public Rational floor(long d) {
        if (d == ) {
            return valueOf();
        }
        long s = scm(this.d);
        if (s == d) {
            return valueOf( * s / d);
        } else if (s == ) {
            return valueOf( * d / d);
        } else {
            return valueOf( * d / d);
        }
    }

    
Returns the closest rational with the specified denominator which is greater or equal than this number.
    public Rational ceil(long d) {
        if (d == ) {
            return valueOf();
        }
        long s = scm(this.d);
        if (s == d) {
            return valueOf(( * s +  - 1) / d);
        } else if (s == ) {
            return valueOf(( * d +  - 1) / d);
        } else {
            return valueOf(( * d +  - 1) / d);
        }
    }
    public Rational multiply(Rational that) {
        if (abs(this.) < .
                && abs(this.) < .
                && abs(that.num) < .
                && abs(that.den) < .) {
            return valueOf(this. * that.num,
                    this. * that.den);
        } else {
            return new Rational(
                    BigInteger.valueOf(this.).multiply(BigInteger.valueOf(that.num)),
                    BigInteger.valueOf(this.).multiply(BigInteger.valueOf(that.den)),
                    true);
        }
    }
    public Rational multiply(long integer) {
        if (integer==0) {
            return ;
        } else if (this. % integer == 0) {
            return valueOf(
                    this.,
                    this. / integer);
        } else if (abs(this.) < .
                && abs(integer) < .) {
            return valueOf(
                    this. * integer,
                    this.);
        } else {
            return new Rational(
                    BigInteger.valueOf(this.).multiply(BigInteger.valueOf(integer)),
                    BigInteger.valueOf(this.), true);
        }
    }
    public Rational divide(Rational that) {
        if (abs(this.) < .
                && abs(this.) < .
                && abs(that.num) < .
                && abs(that.den) < .) {
            return valueOf(this. * that.den,
                    this. * that.num);
        } else {
            return valueOf(
                    BigInteger.valueOf(this.).multiply(BigInteger.valueOf(that.den)),
                    BigInteger.valueOf(this.).multiply(BigInteger.valueOf(that.num)),
                    true);
        }
    }
    @Override
    public String toString() {
        //long gcd = IntMath.gcd(num, den);
        if ( == 0) {
            return "0";
        } else if ( == 1) {
            return Long.toString();
        } else {
            return  + "/" + ;
            /*
             } else {
             return Float.toString((float) num / den);
             */
        }
    }
    public String toDescriptiveString() {
        long gcd = IntMath.gcd();
        if (gcd == 0 ||  == 0) {
            return  + "/" +  + " = " + 0;
        } else if (gcd == ) {
            return  + "/" +  + " = " + Long.toString( / );
        } else {
            return  + "/" +  + " ≈ " + ((float / );
        }
    }
    @Override
    public int intValue() {
        return (int) ( / );
    }
    @Override
    public long longValue() {
        return  / ;
    }
    @Override
    public float floatValue() {
        return (float / (float;
    }
    @Override
    public double doubleValue() {
        return (double / (double;
    }
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Rational that = (Rationalobj;
        return compareTo(that) == 0;
    }

    
return { -1, 0, +1 } if a < b, a = b, or a > b.
    public int compareTo(Rational that) {
        // The following code avoids BigInteger allocation if the denominators 
        // are equal 
        if (this. == that.den) {
            if (this. < that.num) {
                return -1;
            } else if (this. > that.num) {
                return 1;
            } else {
                return 0;
            }
        }
        // Work with longs if overflow can not occur
        if (abs(this.) < .
                && abs(this.) < .
                && abs(that.num) < .
                && abs(that.den) < .) {
            long lhs = this. * that.den;
            long rhs = this. * that.num;
            if (lhs < rhs) {
                return -1;
            } else if (lhs > rhs) {
                return 1;
            } else {
                return 0;
            }
        }
        // Use big integers to avoid overflows
        BigInteger lhs;
        BigInteger rhs;
        lhs = BigInteger.valueOf(this.).multiply(BigInteger.valueOf(that.den));
        rhs = BigInteger.valueOf(this.).multiply(BigInteger.valueOf(that.num));
        return lhs.compareTo(rhs);
    }
    @Override
    public int hashCode() {
        return (int) (( ^ ( >>> 32))
                ^ ( ^ ( >>> 32)));
    }
    public static Rational max(Rational aRational b) {
        return (a.compareTo(b) >= 0) ? a : b;
    }
    public static Rational min(Rational aRational b) {
        return (a.compareTo(b) <= 0) ? a : b;
    }
    public boolean isZero() {
        return  == 0;
    }
    public boolean isLessOrEqualZero() {
        return  <= 0;
    }
    public static Rational valueOf(double d) {
        if (d == 0) {
            return valueOf(0, 1);
        }
        if (abs(d) > .) {
            throw new IllegalArgumentException("Value " + d + " is too big.");
        }
        if (Double.isInfinite(d)) {
            return valueOf((longsignum(d), 0);
        }
        if (Double.isNaN(d)) {
            return valueOf(0, 1); // no way to express a NaN :-(
        }
        return toRational(d., 100);
    }
    public static Rational valueOf(long numlong den) {
        return valueOf(numdentrue);
    }
    private static Rational valueOf(long numlong denboolean reduceFraction) {
        if (num == den) {
            return ;
        }
        if (num == 0) {
            return ;
        }
        return new Rational(numdenreduceFraction);
    }
    public static Rational valueOf(BigInteger numBigInteger den) {
        return valueOf(numdentrue);
    }
    private static Rational valueOf(BigInteger numBigInteger denboolean reduceFraction) {
        if (num.equals(den)) {
            return ;
        }
        if (num.equals(.)) {
            return ;
        }
        return new Rational(numdenreduceFraction);
    }

    
Iteratively computes rational from double.

Reference:
http://www2.fz-juelich.de/video/cpp/html/exercises/exercise/Rational_cpp.html

    private static Rational toRational(double xdouble limitint iterations) {
        double intpart = Math.floor(x);
        double fractpart = x - intpart;
        double d = 1.0 / fractpart;
        long left = (longintpart;
        if (d > limit || iterations == 0) {
            return valueOf(left, 1, false);
        } else {
            return valueOf(left, 1, false).add(toRational(dlimit * 0.1, iterations - 1).inverse(), false);
        }
    }
    public Rational round(long d) {
        if (d == ) {
            return valueOf();
        }
        Rational fl = floor(d);
        Rational diffFl = subtract(fl);
        if (diffFl.isZero()) {
            return fl;
        }
        Rational cl = ceil(d);
        Rational diffCl = subtract(cl);
        if (diffCl.isZero()) {
            return cl;
        }
        if (diffFl.isNegative()) {
            diffFl = diffFl.negate();
        }
        if (diffCl.isNegative()) {
            diffCl = diffCl.negate();
        }
        return diffFl.compareTo(diffCl) <= 0 ? fl : cl;
    }
    private boolean isNegative() {
        return  < 0;
    }

    
Parses a string. A rational can be represented in the following ways:
  • As a long number
  • As a double number
  • As an integer/integer rational number
  • Throws:
    java.lang.NumberFormatException if str can not be parsed.
        public static Rational valueOf(String str) {
            int p = str.indexOf('/');
            if (p != -1) {
                return valueOf(Long.valueOf(str.substring(0, p)), Long.valueOf(str.substring(p + 1)));
            }
            try {
                return valueOf(Long.valueOf(str));
            } catch (NumberFormatException e) {
                return valueOf(Double.valueOf(str));
            }
        }
    New to GrepCode? Check out our FAQ X