001/* A Fraction. 002 003 Copyright (c) 1998-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.math; 029 030/////////////////////////////////////////////////////////////////// 031//// Fraction 032 033/** 034 A class for representing fractions. Fractions are immutable and 035 maintained in lowest terms, with a positive denominator. Thus, 036 1/2 and 2/4 are interpreted as different names for the same number. 037 Any fraction with the value zero is expressed as 0/1 in lowest terms. 038 <p>This class only represents fractions with a determined value, 039 so fractions with a zero in the denominator are not allowed (including 0/0). 040 041 @author Stephen Neuendorffer, Adam Cataldo 042 @version $Id$ 043 @since Ptolemy II 0.2 044 @Pt.ProposedRating Green (neuendor) 045 @Pt.AcceptedRating Yellow (cxh) 046 */ 047public class Fraction extends Object { 048 /** Create a new fraction with the value zero (0/1). 049 */ 050 public Fraction() { 051 _numerator = 0; 052 _denominator = 1; 053 _simplify(); 054 } 055 056 /** Create a new fraction with the value i/1. 057 * @param i The numerator. 058 */ 059 public Fraction(int i) { 060 _numerator = i; 061 _denominator = 1; 062 _simplify(); 063 } 064 065 /** 066 * Create a new fraction in lowest terms 067 * with the value Numerator/Denominator. 068 * @param numerator The numerator. 069 * @param denominator The denominator. 070 * @exception ArithmeticException If the denominator is specified to be 071 * zero. 072 */ 073 public Fraction(int numerator, int denominator) { 074 if (denominator == 0) { 075 throw new ArithmeticException( 076 "Illegal Fraction: " + "cannot have denominator of zero."); 077 } 078 079 _numerator = numerator; 080 _denominator = denominator; 081 _simplify(); 082 } 083 084 /** Create a new fraction with the same value as the given fraction. 085 * @param f The given Fraction. 086 */ 087 public Fraction(Fraction f) { 088 _numerator = f._numerator; 089 _denominator = f._denominator; 090 } 091 092 /////////////////////////////////////////////////////////////////// 093 //// public methods //// 094 095 /** Add this fraction to the given fraction. 096 * @param b The given Fraction. 097 * @return The answer as another fraction in lowest terms. 098 */ 099 public Fraction add(Fraction b) { 100 Fraction f = new Fraction( 101 _numerator * b._denominator + _denominator * b._numerator, 102 _denominator * b._denominator); 103 return f; 104 } 105 106 /** Divide this fraction by the given fraction. 107 * @param b The given Fraction. 108 * @return The answer as another fraction in lowest terms. 109 * @exception ArithmeticException If the fraction in the divisor has 110 * a value of zero. 111 */ 112 public Fraction divide(Fraction b) { 113 if (b.equals(ZERO)) { 114 throw new ArithmeticException("Division by zero!"); 115 } 116 117 Fraction f = new Fraction(_numerator * b._denominator, 118 _denominator * b._numerator); 119 return f; 120 } 121 122 /** Compare this fraction with the given object. 123 * @return True if the given object is a fraction 124 * and equal to this fraction. 125 */ 126 @Override 127 public boolean equals(Object b) { 128 // The Fractions are already in lowest terms, so we just compare the 129 // numerator and denominator 130 if (b instanceof Fraction) { 131 return _numerator == ((Fraction) b)._numerator 132 && _denominator == ((Fraction) b)._denominator; 133 } 134 return false; 135 } 136 137 /** Return the denominator of this fraction. 138 */ 139 public int getDenominator() { 140 return _denominator; 141 } 142 143 /** Return the numerator of this fraction. 144 */ 145 public int getNumerator() { 146 return _numerator; 147 } 148 149 /** Test if this Fraction is greater than the input. 150 * 151 * @param testInput The input to compare against. 152 * @return True if this Fraction is greater than the input. 153 */ 154 public boolean greaterThan(Fraction testInput) { 155 int gcd = ExtendedMath.gcd(testInput.getDenominator(), 156 this.getDenominator()); 157 int thisScaled = this.multiply(new Fraction(gcd, 1)).getNumerator(); 158 int inputScaled = testInput.multiply(new Fraction(gcd, 1)) 159 .getNumerator(); 160 161 if (thisScaled > inputScaled) { 162 return true; 163 } 164 return false; 165 } 166 167 /** Return a hash code value for this Fraction. This method returns the 168 * bitwise and of the hashcode of the denominator and the numerator. 169 * @return A hash code value for this Coordinate 170 */ 171 @Override 172 public int hashCode() { 173 return Integer.valueOf(_denominator).hashCode() 174 & Integer.valueOf(_numerator).hashCode(); 175 } 176 177 /** Find the multiplicative inverse of this fraction. 178 * @return The answer as another fraction in lowest terms 179 * @exception ArithmeticException If this fraction has a value of zero, 180 * in which case the multiplicative inverse cannot be represented. 181 */ 182 public Fraction inverse() { 183 if (equals(ZERO)) { 184 throw new ArithmeticException("Inverse of zero is undefined!"); 185 } 186 187 Fraction f = new Fraction(_denominator, _numerator); 188 return f; 189 } 190 191 /** Finds the least common multiple(LCM) of two integers. 192 * If one of the numbers is negative, then the LCM is negative. 193 * If both of the numbers are negative, then the LCM is positive. 194 * the LCM is least in terms of absolute value. 195 */ 196 197 //FIXME: should this go someplace better? 198 public static int lcm(int u, int v) { 199 int gcd = ExtendedMath.gcd(u, v); 200 int result = u * v / gcd; 201 return result; 202 } 203 204 /** Multiply this fraction by the given fraction. 205 * @return The answer as another fraction in lowest terms. 206 */ 207 public Fraction multiply(Fraction b) { 208 Fraction f = new Fraction(_numerator * b._numerator, 209 _denominator * b._denominator); 210 return f; 211 } 212 213 /** Find the additive inverse of this fraction. 214 * @return The answer as another fraction in lowest terms 215 */ 216 public Fraction negate() { 217 Fraction f = new Fraction(-_numerator, _denominator); 218 return f; 219 } 220 221 /** Subtract the given fraction from this fraction. 222 * @return The answer as another fraction in lowest terms 223 */ 224 public Fraction subtract(Fraction b) { 225 Fraction f = new Fraction( 226 _numerator * b._denominator - _denominator * b._numerator, 227 _denominator * b._denominator); 228 return f; 229 } 230 231 /** Convert the fraction to a double. 232 * @return The double value. 233 */ 234 public double toDouble() { 235 double numerator; 236 double denominator; 237 numerator = _numerator; 238 denominator = _denominator; 239 return numerator / denominator; 240 } 241 242 /** Convert the fraction to a float. 243 * @return The float value. 244 */ 245 public float toFloat() { 246 float numerator; 247 float denominator; 248 numerator = _numerator; 249 denominator = _denominator; 250 return numerator / denominator; 251 } 252 253 /** Convert the fraction to a readable string. 254 */ 255 @Override 256 public String toString() { 257 _simplify(); 258 return _numerator + "/" + _denominator; 259 } 260 261 /////////////////////////////////////////////////////////////////// 262 //// public variables //// 263 264 /** The value of zero as a Fraction. 265 * It is arguable as to whether or not this is needed. It may 266 * reduce the number of object creations, and increase speed, 267 * depending how often a zero fraction is needed. This may become 268 * useful when this class is made into a Token. 269 */ 270 public static final Fraction ZERO = new Fraction(0, 1); 271 272 /** Reduce the fraction to lowest terms by dividing the Numerator and 273 * Denominator by their Greatest Common Divisor. In addition the 274 * fraction is put in standard form (denominator greater than zero). 275 */ 276 protected void _simplify() { 277 int factor = ExtendedMath.gcd(_numerator, _denominator); 278 _numerator = _numerator / factor; 279 _denominator = _denominator / factor; 280 281 // Standardize the sign 282 if (_denominator < 0) { 283 _denominator = -_denominator; 284 _numerator = -_numerator; 285 } 286 } 287 288 /////////////////////////////////////////////////////////////////// 289 //// private variables //// 290 291 private int _numerator; 292 293 private int _denominator; 294}