Coverage Report - org.apache.commons.lang3.math.Fraction
 
Classes in this File Line Coverage Branch Coverage Complexity
Fraction
97%
264/270
91%
180/196
5,353
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.lang3.math;
 18  
 
 19  
 import java.math.BigInteger;
 20  
 
 21  
 /**
 22  
  * <p><code>Fraction</code> is a <code>Number</code> implementation that
 23  
  * stores fractions accurately.</p>
 24  
  *
 25  
  * <p>This class is immutable, and interoperable with most methods that accept
 26  
  * a <code>Number</code>.</p>
 27  
  *
 28  
  * <p>Note that this class is intended for common use cases, it is <i>int</i>
 29  
  * based and thus suffers from various overflow issues. For a BigInteger based 
 30  
  * equivalent, please see the Commons Math BigFraction class. </p>
 31  
  *
 32  
  * @since 2.0
 33  
  */
 34  0
 public final class Fraction extends Number implements Comparable<Fraction> {
 35  
 
 36  
     /**
 37  
      * Required for serialization support. Lang version 2.0.
 38  
      * 
 39  
      * @see java.io.Serializable
 40  
      */
 41  
     private static final long serialVersionUID = 65382027393090L;
 42  
 
 43  
     /**
 44  
      * <code>Fraction</code> representation of 0.
 45  
      */
 46  1
     public static final Fraction ZERO = new Fraction(0, 1);
 47  
     /**
 48  
      * <code>Fraction</code> representation of 1.
 49  
      */
 50  1
     public static final Fraction ONE = new Fraction(1, 1);
 51  
     /**
 52  
      * <code>Fraction</code> representation of 1/2.
 53  
      */
 54  1
     public static final Fraction ONE_HALF = new Fraction(1, 2);
 55  
     /**
 56  
      * <code>Fraction</code> representation of 1/3.
 57  
      */
 58  1
     public static final Fraction ONE_THIRD = new Fraction(1, 3);
 59  
     /**
 60  
      * <code>Fraction</code> representation of 2/3.
 61  
      */
 62  1
     public static final Fraction TWO_THIRDS = new Fraction(2, 3);
 63  
     /**
 64  
      * <code>Fraction</code> representation of 1/4.
 65  
      */
 66  1
     public static final Fraction ONE_QUARTER = new Fraction(1, 4);
 67  
     /**
 68  
      * <code>Fraction</code> representation of 2/4.
 69  
      */
 70  1
     public static final Fraction TWO_QUARTERS = new Fraction(2, 4);
 71  
     /**
 72  
      * <code>Fraction</code> representation of 3/4.
 73  
      */
 74  1
     public static final Fraction THREE_QUARTERS = new Fraction(3, 4);
 75  
     /**
 76  
      * <code>Fraction</code> representation of 1/5.
 77  
      */
 78  1
     public static final Fraction ONE_FIFTH = new Fraction(1, 5);
 79  
     /**
 80  
      * <code>Fraction</code> representation of 2/5.
 81  
      */
 82  1
     public static final Fraction TWO_FIFTHS = new Fraction(2, 5);
 83  
     /**
 84  
      * <code>Fraction</code> representation of 3/5.
 85  
      */
 86  1
     public static final Fraction THREE_FIFTHS = new Fraction(3, 5);
 87  
     /**
 88  
      * <code>Fraction</code> representation of 4/5.
 89  
      */
 90  1
     public static final Fraction FOUR_FIFTHS = new Fraction(4, 5);
 91  
 
 92  
 
 93  
     /**
 94  
      * The numerator number part of the fraction (the three in three sevenths).
 95  
      */
 96  
     private final int numerator;
 97  
     /**
 98  
      * The denominator number part of the fraction (the seven in three sevenths).
 99  
      */
 100  
     private final int denominator;
 101  
 
 102  
     /**
 103  
      * Cached output hashCode (class is immutable).
 104  
      */
 105  199512
     private transient int hashCode = 0;
 106  
     /**
 107  
      * Cached output toString (class is immutable).
 108  
      */
 109  199512
     private transient String toString = null;
 110  
     /**
 111  
      * Cached output toProperString (class is immutable).
 112  
      */
 113  199512
     private transient String toProperString = null;
 114  
 
 115  
     /**
 116  
      * <p>Constructs a <code>Fraction</code> instance with the 2 parts
 117  
      * of a fraction Y/Z.</p>
 118  
      *
 119  
      * @param numerator  the numerator, for example the three in 'three sevenths'
 120  
      * @param denominator  the denominator, for example the seven in 'three sevenths'
 121  
      */
 122  
     private Fraction(final int numerator, final int denominator) {
 123  199512
         super();
 124  199512
         this.numerator = numerator;
 125  199512
         this.denominator = denominator;
 126  199512
     }
 127  
 
 128  
     /**
 129  
      * <p>Creates a <code>Fraction</code> instance with the 2 parts
 130  
      * of a fraction Y/Z.</p>
 131  
      *
 132  
      * <p>Any negative signs are resolved to be on the numerator.</p>
 133  
      *
 134  
      * @param numerator  the numerator, for example the three in 'three sevenths'
 135  
      * @param denominator  the denominator, for example the seven in 'three sevenths'
 136  
      * @return a new fraction instance
 137  
      * @throws ArithmeticException if the denominator is <code>zero</code>
 138  
      * or the denominator is {@code negative} and the numerator is {@code Integer#MIN_VALUE}
 139  
      */
 140  
     public static Fraction getFraction(int numerator, int denominator) {
 141  170
         if (denominator == 0) {
 142  3
             throw new ArithmeticException("The denominator must not be zero");
 143  
         }
 144  167
         if (denominator < 0) {
 145  9
             if (numerator == Integer.MIN_VALUE || denominator == Integer.MIN_VALUE) {
 146  2
                 throw new ArithmeticException("overflow: can't negate");
 147  
             }
 148  7
             numerator = -numerator;
 149  7
             denominator = -denominator;
 150  
         }
 151  165
         return new Fraction(numerator, denominator);
 152  
     }
 153  
 
 154  
     /**
 155  
      * <p>Creates a <code>Fraction</code> instance with the 3 parts
 156  
      * of a fraction X Y/Z.</p>
 157  
      *
 158  
      * <p>The negative sign must be passed in on the whole number part.</p>
 159  
      *
 160  
      * @param whole  the whole number, for example the one in 'one and three sevenths'
 161  
      * @param numerator  the numerator, for example the three in 'one and three sevenths'
 162  
      * @param denominator  the denominator, for example the seven in 'one and three sevenths'
 163  
      * @return a new fraction instance
 164  
      * @throws ArithmeticException if the denominator is <code>zero</code>
 165  
      * @throws ArithmeticException if the denominator is negative
 166  
      * @throws ArithmeticException if the numerator is negative
 167  
      * @throws ArithmeticException if the resulting numerator exceeds 
 168  
      *  <code>Integer.MAX_VALUE</code>
 169  
      */
 170  
     public static Fraction getFraction(final int whole, final int numerator, final int denominator) {
 171  35
         if (denominator == 0) {
 172  3
             throw new ArithmeticException("The denominator must not be zero");
 173  
         }
 174  32
         if (denominator < 0) {
 175  6
             throw new ArithmeticException("The denominator must not be negative");
 176  
         }
 177  26
         if (numerator < 0) {
 178  1
             throw new ArithmeticException("The numerator must not be negative");
 179  
         }
 180  
         long numeratorValue;
 181  25
         if (whole < 0) {
 182  13
             numeratorValue = whole * (long) denominator - numerator;
 183  
         } else {
 184  12
             numeratorValue = whole * (long) denominator + numerator;
 185  
         }
 186  25
         if (numeratorValue < Integer.MIN_VALUE || numeratorValue > Integer.MAX_VALUE) {
 187  4
             throw new ArithmeticException("Numerator too large to represent as an Integer.");
 188  
         }
 189  21
         return new Fraction((int) numeratorValue, denominator);
 190  
     }
 191  
 
 192  
     /**
 193  
      * <p>Creates a reduced <code>Fraction</code> instance with the 2 parts
 194  
      * of a fraction Y/Z.</p>
 195  
      *
 196  
      * <p>For example, if the input parameters represent 2/4, then the created
 197  
      * fraction will be 1/2.</p>
 198  
      *
 199  
      * <p>Any negative signs are resolved to be on the numerator.</p>
 200  
      *
 201  
      * @param numerator  the numerator, for example the three in 'three sevenths'
 202  
      * @param denominator  the denominator, for example the seven in 'three sevenths'
 203  
      * @return a new fraction instance, with the numerator and denominator reduced
 204  
      * @throws ArithmeticException if the denominator is <code>zero</code>
 205  
      */
 206  
     public static Fraction getReducedFraction(int numerator, int denominator) {
 207  199276
         if (denominator == 0) {
 208  3
             throw new ArithmeticException("The denominator must not be zero");
 209  
         }
 210  199273
         if (numerator == 0) {
 211  5
             return ZERO; // normalize zero.
 212  
         }
 213  
         // allow 2^k/-2^31 as a valid fraction (where k>0)
 214  199268
         if (denominator == Integer.MIN_VALUE && (numerator & 1) == 0) {
 215  1
             numerator /= 2;
 216  1
             denominator /= 2;
 217  
         }
 218  199268
         if (denominator < 0) {
 219  4
             if (numerator == Integer.MIN_VALUE || denominator == Integer.MIN_VALUE) {
 220  1
                 throw new ArithmeticException("overflow: can't negate");
 221  
             }
 222  3
             numerator = -numerator;
 223  3
             denominator = -denominator;
 224  
         }
 225  
         // simplify fraction.
 226  199267
         final int gcd = greatestCommonDivisor(numerator, denominator);
 227  199267
         numerator /= gcd;
 228  199267
         denominator /= gcd;
 229  199267
         return new Fraction(numerator, denominator);
 230  
     }
 231  
 
 232  
     /**
 233  
      * <p>Creates a <code>Fraction</code> instance from a <code>double</code> value.</p>
 234  
      *
 235  
      * <p>This method uses the <a href="http://archives.math.utk.edu/articles/atuyl/confrac/">
 236  
      *  continued fraction algorithm</a>, computing a maximum of
 237  
      *  25 convergents and bounding the denominator by 10,000.</p>
 238  
      *
 239  
      * @param value  the double value to convert
 240  
      * @return a new fraction instance that is close to the value
 241  
      * @throws ArithmeticException if <code>|value| &gt; Integer.MAX_VALUE</code> 
 242  
      *  or <code>value = NaN</code>
 243  
      * @throws ArithmeticException if the calculated denominator is <code>zero</code>
 244  
      * @throws ArithmeticException if the the algorithm does not converge
 245  
      */
 246  
     public static Fraction getFraction(double value) {
 247  99584
         final int sign = value < 0 ? -1 : 1;
 248  99584
         value = Math.abs(value);
 249  99584
         if (value > Integer.MAX_VALUE || Double.isNaN(value)) {
 250  4
             throw new ArithmeticException("The value must not be greater than Integer.MAX_VALUE or NaN");
 251  
         }
 252  99580
         final int wholeNumber = (int) value;
 253  99580
         value -= wholeNumber;
 254  
 
 255  99580
         int numer0 = 0; // the pre-previous
 256  99580
         int denom0 = 1; // the pre-previous
 257  99580
         int numer1 = 1; // the previous
 258  99580
         int denom1 = 0; // the previous
 259  99580
         int numer2 = 0; // the current, setup in calculation
 260  99580
         int denom2 = 0; // the current, setup in calculation
 261  99580
         int a1 = (int) value;
 262  99580
         int a2 = 0;
 263  99580
         double x1 = 1;
 264  99580
         double x2 = 0;
 265  99580
         double y1 = value - a1;
 266  99580
         double y2 = 0;
 267  99580
         double delta1, delta2 = Double.MAX_VALUE;
 268  
         double fraction;
 269  99580
         int i = 1;
 270  
         // System.out.println("---");
 271  
         do {
 272  982446
             delta1 = delta2;
 273  982446
             a2 = (int) (x1 / y1);
 274  982446
             x2 = y1;
 275  982446
             y2 = x1 - a2 * y1;
 276  982446
             numer2 = a1 * numer1 + numer0;
 277  982446
             denom2 = a1 * denom1 + denom0;
 278  982446
             fraction = (double) numer2 / (double) denom2;
 279  982446
             delta2 = Math.abs(value - fraction);
 280  
             // System.out.println(numer2 + " " + denom2 + " " + fraction + " " + delta2 + " " + y1);
 281  982446
             a1 = a2;
 282  982446
             x1 = x2;
 283  982446
             y1 = y2;
 284  982446
             numer0 = numer1;
 285  982446
             denom0 = denom1;
 286  982446
             numer1 = numer2;
 287  982446
             denom1 = denom2;
 288  982446
             i++;
 289  
             // System.out.println(">>" + delta1 +" "+ delta2+" "+(delta1 > delta2)+" "+i+" "+denom2);
 290  982446
         } while (delta1 > delta2 && denom2 <= 10000 && denom2 > 0 && i < 25);
 291  99580
         if (i == 25) {
 292  0
             throw new ArithmeticException("Unable to convert double to fraction");
 293  
         }
 294  99580
         return getReducedFraction((numer0 + wholeNumber * denom0) * sign, denom0);
 295  
     }
 296  
 
 297  
     /**
 298  
      * <p>Creates a Fraction from a <code>String</code>.</p>
 299  
      *
 300  
      * <p>The formats accepted are:</p>
 301  
      *
 302  
      * <ol>
 303  
      *  <li><code>double</code> String containing a dot</li>
 304  
      *  <li>'X Y/Z'</li>
 305  
      *  <li>'Y/Z'</li>
 306  
      *  <li>'X' (a simple whole number)</li>
 307  
      * </ol>
 308  
      * <p>and a .</p>
 309  
      *
 310  
      * @param str  the string to parse, must not be <code>null</code>
 311  
      * @return the new <code>Fraction</code> instance
 312  
      * @throws IllegalArgumentException if the string is <code>null</code>
 313  
      * @throws NumberFormatException if the number format is invalid
 314  
      */
 315  
     public static Fraction getFraction(String str) {
 316  30
         if (str == null) {
 317  1
             throw new IllegalArgumentException("The string must not be null");
 318  
         }
 319  
         // parse double format
 320  29
         int pos = str.indexOf('.');
 321  29
         if (pos >= 0) {
 322  6
             return getFraction(Double.parseDouble(str));
 323  
         }
 324  
 
 325  
         // parse X Y/Z format
 326  23
         pos = str.indexOf(' ');
 327  23
         if (pos > 0) {
 328  10
             final int whole = Integer.parseInt(str.substring(0, pos));
 329  9
             str = str.substring(pos + 1);
 330  9
             pos = str.indexOf('/');
 331  9
             if (pos < 0) {
 332  2
                 throw new NumberFormatException("The fraction could not be parsed as the format X Y/Z");
 333  
             }
 334  7
             final int numer = Integer.parseInt(str.substring(0, pos));
 335  6
             final int denom = Integer.parseInt(str.substring(pos + 1));
 336  6
             return getFraction(whole, numer, denom);
 337  
         }
 338  
 
 339  
         // parse Y/Z format
 340  13
         pos = str.indexOf('/');
 341  13
         if (pos < 0) {
 342  
             // simple whole number
 343  3
             return getFraction(Integer.parseInt(str), 1);
 344  
         }
 345  10
         final int numer = Integer.parseInt(str.substring(0, pos));
 346  8
         final int denom = Integer.parseInt(str.substring(pos + 1));
 347  6
         return getFraction(numer, denom);
 348  
     }
 349  
 
 350  
     // Accessors
 351  
     //-------------------------------------------------------------------
 352  
 
 353  
     /**
 354  
      * <p>Gets the numerator part of the fraction.</p>
 355  
      *
 356  
      * <p>This method may return a value greater than the denominator, an
 357  
      * improper fraction, such as the seven in 7/4.</p>
 358  
      *
 359  
      * @return the numerator fraction part
 360  
      */
 361  
     public int getNumerator() {
 362  199294
         return numerator;
 363  
     }
 364  
 
 365  
     /**
 366  
      * <p>Gets the denominator part of the fraction.</p>
 367  
      *
 368  
      * @return the denominator fraction part
 369  
      */
 370  
     public int getDenominator() {
 371  199292
         return denominator;
 372  
     }
 373  
 
 374  
     /**
 375  
      * <p>Gets the proper numerator, always positive.</p>
 376  
      *
 377  
      * <p>An improper fraction 7/4 can be resolved into a proper one, 1 3/4.
 378  
      * This method returns the 3 from the proper fraction.</p>
 379  
      *
 380  
      * <p>If the fraction is negative such as -7/4, it can be resolved into
 381  
      * -1 3/4, so this method returns the positive proper numerator, 3.</p>
 382  
      *
 383  
      * @return the numerator fraction part of a proper fraction, always positive
 384  
      */
 385  
     public int getProperNumerator() {
 386  9
         return Math.abs(numerator % denominator);
 387  
     }
 388  
 
 389  
     /**
 390  
      * <p>Gets the proper whole part of the fraction.</p>
 391  
      *
 392  
      * <p>An improper fraction 7/4 can be resolved into a proper one, 1 3/4.
 393  
      * This method returns the 1 from the proper fraction.</p>
 394  
      *
 395  
      * <p>If the fraction is negative such as -7/4, it can be resolved into
 396  
      * -1 3/4, so this method returns the positive whole part -1.</p>
 397  
      *
 398  
      * @return the whole fraction part of a proper fraction, that includes the sign
 399  
      */
 400  
     public int getProperWhole() {
 401  9
         return numerator / denominator;
 402  
     }
 403  
 
 404  
     // Number methods
 405  
     //-------------------------------------------------------------------
 406  
 
 407  
     /**
 408  
      * <p>Gets the fraction as an <code>int</code>. This returns the whole number
 409  
      * part of the fraction.</p>
 410  
      *
 411  
      * @return the whole number fraction part
 412  
      */
 413  
     @Override
 414  
     public int intValue() {
 415  1
         return numerator / denominator;
 416  
     }
 417  
 
 418  
     /**
 419  
      * <p>Gets the fraction as a <code>long</code>. This returns the whole number
 420  
      * part of the fraction.</p>
 421  
      *
 422  
      * @return the whole number fraction part
 423  
      */
 424  
     @Override
 425  
     public long longValue() {
 426  1
         return (long) numerator / denominator;
 427  
     }
 428  
 
 429  
     /**
 430  
      * <p>Gets the fraction as a <code>float</code>. This calculates the fraction
 431  
      * as the numerator divided by denominator.</p>
 432  
      *
 433  
      * @return the fraction as a <code>float</code>
 434  
      */
 435  
     @Override
 436  
     public float floatValue() {
 437  1
         return (float) numerator / (float) denominator;
 438  
     }
 439  
 
 440  
     /**
 441  
      * <p>Gets the fraction as a <code>double</code>. This calculates the fraction
 442  
      * as the numerator divided by denominator.</p>
 443  
      *
 444  
      * @return the fraction as a <code>double</code>
 445  
      */
 446  
     @Override
 447  
     public double doubleValue() {
 448  1
         return (double) numerator / (double) denominator;
 449  
     }
 450  
 
 451  
     // Calculations
 452  
     //-------------------------------------------------------------------
 453  
 
 454  
     /**
 455  
      * <p>Reduce the fraction to the smallest values for the numerator and
 456  
      * denominator, returning the result.</p>
 457  
      * 
 458  
      * <p>For example, if this fraction represents 2/4, then the result
 459  
      * will be 1/2.</p>
 460  
      *
 461  
      * @return a new reduced fraction instance, or this if no simplification possible
 462  
      */
 463  
     public Fraction reduce() {
 464  8
         if (numerator == 0) {
 465  2
             return equals(ZERO) ? this : ZERO;
 466  
         }
 467  6
         final int gcd = greatestCommonDivisor(Math.abs(numerator), denominator);
 468  6
         if (gcd == 1) {
 469  4
             return this;
 470  
         }
 471  2
         return Fraction.getFraction(numerator / gcd, denominator / gcd);
 472  
     }
 473  
 
 474  
     /**
 475  
      * <p>Gets a fraction that is the inverse (1/fraction) of this one.</p>
 476  
      * 
 477  
      * <p>The returned fraction is not reduced.</p>
 478  
      *
 479  
      * @return a new fraction instance with the numerator and denominator
 480  
      *         inverted.
 481  
      * @throws ArithmeticException if the fraction represents zero.
 482  
      */
 483  
     public Fraction invert() {
 484  23
         if (numerator == 0) {
 485  3
             throw new ArithmeticException("Unable to invert zero.");
 486  
         }
 487  20
         if (numerator==Integer.MIN_VALUE) {
 488  1
             throw new ArithmeticException("overflow: can't negate numerator");
 489  
         }
 490  19
         if (numerator<0) {
 491  3
             return new Fraction(-denominator, -numerator);
 492  
         }
 493  16
         return new Fraction(denominator, numerator);
 494  
     }
 495  
 
 496  
     /**
 497  
      * <p>Gets a fraction that is the negative (-fraction) of this one.</p>
 498  
      *
 499  
      * <p>The returned fraction is not reduced.</p>
 500  
      *
 501  
      * @return a new fraction instance with the opposite signed numerator
 502  
      */
 503  
     public Fraction negate() {
 504  
         // the positive range is one smaller than the negative range of an int.
 505  11
         if (numerator==Integer.MIN_VALUE) {
 506  2
             throw new ArithmeticException("overflow: too large to negate");
 507  
         }
 508  9
         return new Fraction(-numerator, denominator);
 509  
     }
 510  
 
 511  
     /**
 512  
      * <p>Gets a fraction that is the positive equivalent of this one.</p>
 513  
      * <p>More precisely: <code>(fraction &gt;= 0 ? this : -fraction)</code></p>
 514  
      *
 515  
      * <p>The returned fraction is not reduced.</p>
 516  
      *
 517  
      * @return <code>this</code> if it is positive, or a new positive fraction
 518  
      *  instance with the opposite signed numerator
 519  
      */
 520  
     public Fraction abs() {
 521  5
         if (numerator >= 0) {
 522  2
             return this;
 523  
         }
 524  3
         return negate();
 525  
     }
 526  
 
 527  
     /**
 528  
      * <p>Gets a fraction that is raised to the passed in power.</p>
 529  
      *
 530  
      * <p>The returned fraction is in reduced form.</p>
 531  
      *
 532  
      * @param power  the power to raise the fraction to
 533  
      * @return <code>this</code> if the power is one, <code>ONE</code> if the power
 534  
      * is zero (even if the fraction equals ZERO) or a new fraction instance 
 535  
      * raised to the appropriate power
 536  
      * @throws ArithmeticException if the resulting numerator or denominator exceeds
 537  
      *  <code>Integer.MAX_VALUE</code>
 538  
      */
 539  
     public Fraction pow(final int power) {
 540  101
         if (power == 1) {
 541  19
             return this;
 542  82
         } else if (power == 0) {
 543  3
             return ONE;
 544  79
         } else if (power < 0) {
 545  8
             if (power == Integer.MIN_VALUE) { // MIN_VALUE can't be negated.
 546  2
                 return this.invert().pow(2).pow(-(power / 2));
 547  
             }
 548  6
             return this.invert().pow(-power);
 549  
         } else {
 550  71
             final Fraction f = this.multiplyBy(this);
 551  68
             if (power % 2 == 0) { // if even...
 552  36
                 return f.pow(power / 2);
 553  
             }
 554  32
             return f.pow(power / 2).multiplyBy(this);
 555  
         }
 556  
     }
 557  
 
 558  
     /**
 559  
      * <p>Gets the greatest common divisor of the absolute value of
 560  
      * two numbers, using the "binary gcd" method which avoids
 561  
      * division and modulo operations.  See Knuth 4.5.2 algorithm B.
 562  
      * This algorithm is due to Josef Stein (1961).</p>
 563  
      *
 564  
      * @param u  a non-zero number
 565  
      * @param v  a non-zero number
 566  
      * @return the greatest common divisor, never zero
 567  
      */
 568  
     private static int greatestCommonDivisor(int u, int v) {
 569  
         // From Commons Math:
 570  199549
         if (u == 0 || v == 0) {
 571  0
             if (u == Integer.MIN_VALUE || v == Integer.MIN_VALUE) {
 572  0
                 throw new ArithmeticException("overflow: gcd is 2^31");
 573  
             }
 574  0
             return Math.abs(u) + Math.abs(v);
 575  
         }
 576  
         // if either operand is abs 1, return 1:
 577  199549
         if (Math.abs(u) == 1 || Math.abs(v) == 1) {
 578  1000
             return 1;
 579  
         }
 580  
         // keep u and v negative, as negative integers range down to
 581  
         // -2^31, while positive numbers can only be as large as 2^31-1
 582  
         // (i.e. we can't necessarily negate a negative number without
 583  
         // overflow)
 584  198549
         if (u > 0) {
 585  198540
             u = -u;
 586  
         } // make u negative
 587  198549
         if (v > 0) {
 588  198549
             v = -v;
 589  
         } // make v negative
 590  
         // B1. [Find power of 2]
 591  198549
         int k = 0;
 592  200274
         while ((u & 1) == 0 && (v & 1) == 0 && k < 31) { // while u and v are both even...
 593  1725
             u /= 2;
 594  1725
             v /= 2;
 595  1725
             k++; // cast out twos.
 596  
         }
 597  198549
         if (k == 31) {
 598  0
             throw new ArithmeticException("overflow: gcd is 2^31");
 599  
         }
 600  
         // B2. Initialize: u and v have been divided by 2^k and at least
 601  
         // one is odd.
 602  198549
         int t = (u & 1) == 1 ? v : -(u / 2)/* B3 */;
 603  
         // t negative: u was odd, v may be even (t replaces v)
 604  
         // t positive: u was even, v is odd (t replaces u)
 605  
         do {
 606  
             /* assert u<0 && v<0; */
 607  
             // B4/B3: cast out twos from t.
 608  3303752
             while ((t & 1) == 0) { // while t is even..
 609  1498661
                 t /= 2; // cast out twos
 610  
             }
 611  
             // B5 [reset max(u,v)]
 612  1805091
             if (t > 0) {
 613  821671
                 u = -t;
 614  
             } else {
 615  983420
                 v = t;
 616  
             }
 617  
             // B6/B3. at this point both u and v should be odd.
 618  1805091
             t = (v - u) / 2;
 619  
             // |u| larger: t positive (replace u)
 620  
             // |v| larger: t negative (replace v)
 621  1805091
         } while (t != 0);
 622  198549
         return -u * (1 << k); // gcd is u*2^k
 623  
     }
 624  
 
 625  
     // Arithmetic
 626  
     //-------------------------------------------------------------------
 627  
 
 628  
     /** 
 629  
      * Multiply two integers, checking for overflow.
 630  
      * 
 631  
      * @param x a factor
 632  
      * @param y a factor
 633  
      * @return the product <code>x*y</code>
 634  
      * @throws ArithmeticException if the result can not be represented as
 635  
      *                             an int
 636  
      */
 637  
     private static int mulAndCheck(final int x, final int y) {
 638  143
         final long m = (long) x * (long) y;
 639  143
         if (m < Integer.MIN_VALUE || m > Integer.MAX_VALUE) {
 640  3
             throw new ArithmeticException("overflow: mul");
 641  
         }
 642  140
         return (int) m;
 643  
     }
 644  
     
 645  
     /**
 646  
      *  Multiply two non-negative integers, checking for overflow.
 647  
      * 
 648  
      * @param x a non-negative factor
 649  
      * @param y a non-negative factor
 650  
      * @return the product <code>x*y</code>
 651  
      * @throws ArithmeticException if the result can not be represented as
 652  
      * an int
 653  
      */
 654  
     private static int mulPosAndCheck(final int x, final int y) {
 655  
         /* assert x>=0 && y>=0; */
 656  136
         final long m = (long) x * (long) y;
 657  136
         if (m > Integer.MAX_VALUE) {
 658  7
             throw new ArithmeticException("overflow: mulPos");
 659  
         }
 660  129
         return (int) m;
 661  
     }
 662  
     
 663  
     /** 
 664  
      * Add two integers, checking for overflow.
 665  
      * 
 666  
      * @param x an addend
 667  
      * @param y an addend
 668  
      * @return the sum <code>x+y</code>
 669  
      * @throws ArithmeticException if the result can not be represented as
 670  
      * an int
 671  
      */
 672  
     private static int addAndCheck(final int x, final int y) {
 673  7
         final long s = (long) x + (long) y;
 674  7
         if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) {
 675  3
             throw new ArithmeticException("overflow: add");
 676  
         }
 677  4
         return (int) s;
 678  
     }
 679  
     
 680  
     /** 
 681  
      * Subtract two integers, checking for overflow.
 682  
      * 
 683  
      * @param x the minuend
 684  
      * @param y the subtrahend
 685  
      * @return the difference <code>x-y</code>
 686  
      * @throws ArithmeticException if the result can not be represented as
 687  
      * an int
 688  
      */
 689  
     private static int subAndCheck(final int x, final int y) {
 690  6
         final long s = (long) x - (long) y;
 691  6
         if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) {
 692  2
             throw new ArithmeticException("overflow: add");
 693  
         }
 694  4
         return (int) s;
 695  
     }
 696  
     
 697  
     /**
 698  
      * <p>Adds the value of this fraction to another, returning the result in reduced form.
 699  
      * The algorithm follows Knuth, 4.5.1.</p>
 700  
      *
 701  
      * @param fraction  the fraction to add, must not be <code>null</code>
 702  
      * @return a <code>Fraction</code> instance with the resulting values
 703  
      * @throws IllegalArgumentException if the fraction is <code>null</code>
 704  
      * @throws ArithmeticException if the resulting numerator or denominator exceeds
 705  
      *  <code>Integer.MAX_VALUE</code>
 706  
      */
 707  
     public Fraction add(final Fraction fraction) {
 708  19
         return addSub(fraction, true /* add */);
 709  
     }
 710  
 
 711  
     /**
 712  
      * <p>Subtracts the value of another fraction from the value of this one, 
 713  
      * returning the result in reduced form.</p>
 714  
      *
 715  
      * @param fraction  the fraction to subtract, must not be <code>null</code>
 716  
      * @return a <code>Fraction</code> instance with the resulting values
 717  
      * @throws IllegalArgumentException if the fraction is <code>null</code>
 718  
      * @throws ArithmeticException if the resulting numerator or denominator
 719  
      *   cannot be represented in an <code>int</code>.
 720  
      */
 721  
     public Fraction subtract(final Fraction fraction) {
 722  17
         return addSub(fraction, false /* subtract */);
 723  
     }
 724  
 
 725  
     /** 
 726  
      * Implement add and subtract using algorithm described in Knuth 4.5.1.
 727  
      * 
 728  
      * @param fraction the fraction to subtract, must not be <code>null</code>
 729  
      * @param isAdd true to add, false to subtract
 730  
      * @return a <code>Fraction</code> instance with the resulting values
 731  
      * @throws IllegalArgumentException if the fraction is <code>null</code>
 732  
      * @throws ArithmeticException if the resulting numerator or denominator
 733  
      *   cannot be represented in an <code>int</code>.
 734  
      */
 735  
     private Fraction addSub(final Fraction fraction, final boolean isAdd) {
 736  36
         if (fraction == null) {
 737  2
             throw new IllegalArgumentException("The fraction must not be null");
 738  
         }
 739  
         // zero is identity for addition.
 740  34
         if (numerator == 0) {
 741  3
             return isAdd ? fraction : fraction.negate();
 742  
         }
 743  31
         if (fraction.numerator == 0) {
 744  2
             return this;
 745  
         }
 746  
         // if denominators are randomly distributed, d1 will be 1 about 61%
 747  
         // of the time.
 748  29
         final int d1 = greatestCommonDivisor(denominator, fraction.denominator);
 749  29
         if (d1 == 1) {
 750  
             // result is ( (u*v' +/- u'v) / u'v')
 751  13
             final int uvp = mulAndCheck(numerator, fraction.denominator);
 752  13
             final int upv = mulAndCheck(fraction.numerator, denominator);
 753  13
             return new Fraction(isAdd ? addAndCheck(uvp, upv) : subAndCheck(uvp, upv), mulPosAndCheck(denominator,
 754  
                     fraction.denominator));
 755  
         }
 756  
         // the quantity 't' requires 65 bits of precision; see knuth 4.5.1
 757  
         // exercise 7. we're going to use a BigInteger.
 758  
         // t = u(v'/d1) +/- v(u'/d1)
 759  16
         final BigInteger uvp = BigInteger.valueOf(numerator).multiply(BigInteger.valueOf(fraction.denominator / d1));
 760  16
         final BigInteger upv = BigInteger.valueOf(fraction.numerator).multiply(BigInteger.valueOf(denominator / d1));
 761  16
         final BigInteger t = isAdd ? uvp.add(upv) : uvp.subtract(upv);
 762  
         // but d2 doesn't need extra precision because
 763  
         // d2 = gcd(t,d1) = gcd(t mod d1, d1)
 764  16
         final int tmodd1 = t.mod(BigInteger.valueOf(d1)).intValue();
 765  16
         final int d2 = tmodd1 == 0 ? d1 : greatestCommonDivisor(tmodd1, d1);
 766  
 
 767  
         // result is (t/d2) / (u'/d1)(v'/d2)
 768  16
         final BigInteger w = t.divide(BigInteger.valueOf(d2));
 769  16
         if (w.bitLength() > 31) {
 770  2
             throw new ArithmeticException("overflow: numerator too large after multiply");
 771  
         }
 772  14
         return new Fraction(w.intValue(), mulPosAndCheck(denominator / d1, fraction.denominator / d2));
 773  
     }
 774  
 
 775  
     /**
 776  
      * <p>Multiplies the value of this fraction by another, returning the 
 777  
      * result in reduced form.</p>
 778  
      *
 779  
      * @param fraction  the fraction to multiply by, must not be <code>null</code>
 780  
      * @return a <code>Fraction</code> instance with the resulting values
 781  
      * @throws IllegalArgumentException if the fraction is <code>null</code>
 782  
      * @throws ArithmeticException if the resulting numerator or denominator exceeds
 783  
      *  <code>Integer.MAX_VALUE</code>
 784  
      */
 785  
     public Fraction multiplyBy(final Fraction fraction) {
 786  121
         if (fraction == null) {
 787  1
             throw new IllegalArgumentException("The fraction must not be null");
 788  
         }
 789  120
         if (numerator == 0 || fraction.numerator == 0) {
 790  3
             return ZERO;
 791  
         }
 792  
         // knuth 4.5.1
 793  
         // make sure we don't overflow unless the result *must* overflow.
 794  117
         final int d1 = greatestCommonDivisor(numerator, fraction.denominator);
 795  117
         final int d2 = greatestCommonDivisor(fraction.numerator, denominator);
 796  117
         return getReducedFraction(mulAndCheck(numerator / d1, fraction.numerator / d2),
 797  
                 mulPosAndCheck(denominator / d2, fraction.denominator / d1));
 798  
     }
 799  
 
 800  
     /**
 801  
      * <p>Divide the value of this fraction by another.</p>
 802  
      *
 803  
      * @param fraction  the fraction to divide by, must not be <code>null</code>
 804  
      * @return a <code>Fraction</code> instance with the resulting values
 805  
      * @throws IllegalArgumentException if the fraction is <code>null</code>
 806  
      * @throws ArithmeticException if the fraction to divide by is zero
 807  
      * @throws ArithmeticException if the resulting numerator or denominator exceeds
 808  
      *  <code>Integer.MAX_VALUE</code>
 809  
      */
 810  
     public Fraction divideBy(final Fraction fraction) {
 811  9
         if (fraction == null) {
 812  1
             throw new IllegalArgumentException("The fraction must not be null");
 813  
         }
 814  8
         if (fraction.numerator == 0) {
 815  1
             throw new ArithmeticException("The fraction to divide by must not be zero");
 816  
         }
 817  7
         return multiplyBy(fraction.invert());
 818  
     }
 819  
 
 820  
     // Basics
 821  
     //-------------------------------------------------------------------
 822  
 
 823  
     /**
 824  
      * <p>Compares this fraction to another object to test if they are equal.</p>.
 825  
      *
 826  
      * <p>To be equal, both values must be equal. Thus 2/4 is not equal to 1/2.</p>
 827  
      *
 828  
      * @param obj the reference object with which to compare
 829  
      * @return <code>true</code> if this object is equal
 830  
      */
 831  
     @Override
 832  
     public boolean equals(final Object obj) {
 833  20
         if (obj == this) {
 834  8
             return true;
 835  
         }
 836  12
         if (obj instanceof Fraction == false) {
 837  3
             return false;
 838  
         }
 839  9
         final Fraction other = (Fraction) obj;
 840  9
         return getNumerator() == other.getNumerator() && getDenominator() == other.getDenominator();
 841  
     }
 842  
 
 843  
     /**
 844  
      * <p>Gets a hashCode for the fraction.</p>
 845  
      *
 846  
      * @return a hash code value for this object
 847  
      */
 848  
     @Override
 849  
     public int hashCode() {
 850  6
         if (hashCode == 0) {
 851  
             // hashcode update should be atomic.
 852  4
             hashCode = 37 * (37 * 17 + getNumerator()) + getDenominator();
 853  
         }
 854  6
         return hashCode;
 855  
     }
 856  
 
 857  
     /**
 858  
      * <p>Compares this object to another based on size.</p>
 859  
      *
 860  
      * <p>Note: this class has a natural ordering that is inconsistent
 861  
      * with equals, because, for example, equals treats 1/2 and 2/4 as
 862  
      * different, whereas compareTo treats them as equal.
 863  
      *
 864  
      * @param other  the object to compare to
 865  
      * @return -1 if this is less, 0 if equal, +1 if greater
 866  
      * @throws ClassCastException if the object is not a <code>Fraction</code>
 867  
      * @throws NullPointerException if the object is <code>null</code>
 868  
      */
 869  
     @Override
 870  
     public int compareTo(final Fraction other) {
 871  14
         if (this == other) {
 872  7
             return 0;
 873  
         }
 874  7
         if (numerator == other.numerator && denominator == other.denominator) {
 875  1
             return 0;
 876  
         }
 877  
 
 878  
         // otherwise see which is less
 879  5
         final long first = (long) numerator * (long) other.denominator;
 880  5
         final long second = (long) other.numerator * (long) denominator;
 881  5
         if (first == second) {
 882  2
             return 0;
 883  3
         } else if (first < second) {
 884  1
             return -1;
 885  
         } else {
 886  2
             return 1;
 887  
         }
 888  
     }
 889  
 
 890  
     /**
 891  
      * <p>Gets the fraction as a <code>String</code>.</p>
 892  
      *
 893  
      * <p>The format used is '<i>numerator</i>/<i>denominator</i>' always.
 894  
      *
 895  
      * @return a <code>String</code> form of the fraction
 896  
      */
 897  
     @Override
 898  
     public String toString() {
 899  8
         if (toString == null) {
 900  7
             toString = new StringBuilder(32).append(getNumerator()).append('/').append(getDenominator()).toString();
 901  
         }
 902  8
         return toString;
 903  
     }
 904  
 
 905  
     /**
 906  
      * <p>Gets the fraction as a proper <code>String</code> in the format X Y/Z.</p>
 907  
      *
 908  
      * <p>The format used in '<i>wholeNumber</i> <i>numerator</i>/<i>denominator</i>'.
 909  
      * If the whole number is zero it will be omitted. If the numerator is zero,
 910  
      * only the whole number is returned.</p>
 911  
      *
 912  
      * @return a <code>String</code> form of the fraction
 913  
      */
 914  
     public String toProperString() {
 915  11
         if (toProperString == null) {
 916  10
             if (numerator == 0) {
 917  1
                 toProperString = "0";
 918  9
             } else if (numerator == denominator) {
 919  1
                 toProperString = "1";
 920  8
             } else if (numerator == -1 * denominator) {
 921  1
                 toProperString = "-1";
 922  7
             } else if ((numerator > 0 ? -numerator : numerator) < -denominator) {
 923  
                 // note that we do the magnitude comparison test above with
 924  
                 // NEGATIVE (not positive) numbers, since negative numbers
 925  
                 // have a larger range. otherwise numerator==Integer.MIN_VALUE
 926  
                 // is handled incorrectly.
 927  6
                 final int properNumerator = getProperNumerator();
 928  6
                 if (properNumerator == 0) {
 929  2
                     toProperString = Integer.toString(getProperWhole());
 930  
                 } else {
 931  4
                     toProperString = new StringBuilder(32).append(getProperWhole()).append(' ').append(properNumerator)
 932  
                             .append('/').append(getDenominator()).toString();
 933  
                 }
 934  6
             } else {
 935  1
                 toProperString = new StringBuilder(32).append(getNumerator()).append('/').append(getDenominator())
 936  
                         .toString();
 937  
             }
 938  
         }
 939  11
         return toProperString;
 940  
     }
 941  
 }