001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.lang3.math; 018 019import java.io.IOException; 020import java.io.InvalidObjectException; 021import java.io.ObjectInputStream; 022import java.io.Serializable; 023import java.math.BigInteger; 024import java.util.Objects; 025 026/** 027 * {@link Fraction} is a {@link Number} implementation that stores fractions accurately. 028 * <p> 029 * This class is immutable, and interoperable with most methods that accept a {@link Number}. 030 * </p> 031 * <p> 032 * Note that this class is intended for common use cases, it is <em>int</em> based and thus suffers from various overflow issues. For a BigInteger based 033 * equivalent, please see the Commons Math BigFraction class. 034 * </p> 035 * 036 * @since 2.0 037 */ 038public final class Fraction extends Number implements Comparable<Fraction> { 039 040 /** 041 * Required for serialization support. Lang version 2.0. 042 * 043 * @see Serializable 044 */ 045 private static final long serialVersionUID = 65382027393090L; 046 047 /** 048 * {@link Fraction} representation of 0. 049 */ 050 public static final Fraction ZERO = new Fraction(0, 1); 051 052 /** 053 * {@link Fraction} representation of 1. 054 */ 055 public static final Fraction ONE = new Fraction(1, 1); 056 057 /** 058 * {@link Fraction} representation of 1/2. 059 */ 060 public static final Fraction ONE_HALF = new Fraction(1, 2); 061 062 /** 063 * {@link Fraction} representation of 1/3. 064 */ 065 public static final Fraction ONE_THIRD = new Fraction(1, 3); 066 067 /** 068 * {@link Fraction} representation of 2/3. 069 */ 070 public static final Fraction TWO_THIRDS = new Fraction(2, 3); 071 072 /** 073 * {@link Fraction} representation of 1/4. 074 */ 075 public static final Fraction ONE_QUARTER = new Fraction(1, 4); 076 077 /** 078 * {@link Fraction} representation of 2/4. 079 */ 080 public static final Fraction TWO_QUARTERS = new Fraction(2, 4); 081 082 /** 083 * {@link Fraction} representation of 3/4. 084 */ 085 public static final Fraction THREE_QUARTERS = new Fraction(3, 4); 086 087 /** 088 * {@link Fraction} representation of 1/5. 089 */ 090 public static final Fraction ONE_FIFTH = new Fraction(1, 5); 091 092 /** 093 * {@link Fraction} representation of 2/5. 094 */ 095 public static final Fraction TWO_FIFTHS = new Fraction(2, 5); 096 097 /** 098 * {@link Fraction} representation of 3/5. 099 */ 100 public static final Fraction THREE_FIFTHS = new Fraction(3, 5); 101 102 /** 103 * {@link Fraction} representation of 4/5. 104 */ 105 public static final Fraction FOUR_FIFTHS = new Fraction(4, 5); 106 107 /** 108 * Checks that a denominator is not zero. 109 * 110 * @param denominator The denominator to check 111 * @throws ArithmeticException Thrown if the denominator is zero. 112 */ 113 private static void checkDenominator(final int denominator) { 114 if (denominator == 0) { 115 throw new ArithmeticException("The denominator must not be zero"); 116 } 117 } 118 119 /** 120 * Gets a {@link Fraction} instance from a {@code double} value. 121 * <p> 122 * This method uses the <a href="https://web.archive.org/web/20210516065058/http%3A//archives.math.utk.edu/articles/atuyl/confrac/"> continued fraction 123 * algorithm</a>, computing a maximum of 25 convergents and bounding the denominator by 10,000. 124 * </p> 125 * 126 * @param value The double value to convert 127 * @return A new fraction instance that is close to the value 128 * @throws ArithmeticException Thrown if {@code |value| > Integer.MAX_VALUE} or {@code value = NaN}. 129 * @throws ArithmeticException Thrown if the calculated denominator is {@code zero}. 130 * @throws ArithmeticException Thrown if the algorithm does not converge. 131 */ 132 public static Fraction getFraction(double value) { 133 final int sign = value < 0 ? -1 : 1; 134 value = Math.abs(value); 135 if (value > Integer.MAX_VALUE || Double.isNaN(value)) { 136 throw new ArithmeticException("The value must not be greater than Integer.MAX_VALUE or NaN"); 137 } 138 final int wholeNumber = (int) value; 139 value -= wholeNumber; 140 int numer0 = 0; // the pre-previous 141 int denom0 = 1; // the pre-previous 142 int numer1 = 1; // the previous 143 int denom1 = 0; // the previous 144 int numer2; // the current, setup in calculation 145 int denom2; // the current, setup in calculation 146 int a1 = (int) value; 147 int a2; 148 double x1 = 1; 149 double x2; 150 double y1 = value - a1; 151 double y2; 152 double delta1; 153 double delta2 = Double.MAX_VALUE; 154 double fraction; 155 int i = 1; 156 do { 157 delta1 = delta2; 158 a2 = (int) (x1 / y1); 159 x2 = y1; 160 y2 = x1 - a2 * y1; 161 numer2 = a1 * numer1 + numer0; 162 denom2 = a1 * denom1 + denom0; 163 fraction = (double) numer2 / (double) denom2; 164 delta2 = Math.abs(value - fraction); 165 a1 = a2; 166 x1 = x2; 167 y1 = y2; 168 numer0 = numer1; 169 denom0 = denom1; 170 numer1 = numer2; 171 denom1 = denom2; 172 i++; 173 } while (delta1 > delta2 && denom2 <= 10000 && denom2 > 0 && i < 25); 174 if (i == 25) { 175 throw new ArithmeticException("Unable to convert double to fraction"); 176 } 177 // wholeNumber can be up to Integer.MAX_VALUE while denom0 > 1 for any non-integer value, 178 // so the int product overflows for values near the limit; check it instead of wrapping silently. 179 final int numerator = Math.addExact(numer0, mulAndCheck(wholeNumber, denom0)); 180 return getReducedFraction(numerator * sign, denom0); 181 } 182 183 /** 184 * Gets a {@link Fraction} instance with the 2 parts of a fraction Y/Z. 185 * <p> 186 * Any negative signs are resolved to be on the numerator. 187 * </p> 188 * 189 * @param numerator The numerator, for example the three in 'three sevenths' 190 * @param denominator The denominator, for example the seven in 'three sevenths' 191 * @return A new fraction instance 192 * @throws ArithmeticException Thrown if the denominator is {@code zero} or the denominator is {@code negative} and the numerator is 193 * {@code Integer#MIN_VALUE}. 194 */ 195 public static Fraction getFraction(int numerator, int denominator) { 196 checkDenominator(denominator); 197 if (denominator < 0) { 198 if (numerator == Integer.MIN_VALUE || denominator == Integer.MIN_VALUE) { 199 throw new ArithmeticException("overflow: can't negate"); 200 } 201 numerator = -numerator; 202 denominator = -denominator; 203 } 204 return new Fraction(numerator, denominator); 205 } 206 207 /** 208 * Gets a {@link Fraction} instance with the 3 parts of a fraction X Y/Z. 209 * <p> 210 * The negative sign must be passed in on the whole number part. 211 * </p> 212 * 213 * @param whole The whole number, for example the one in 'one and three sevenths' 214 * @param numerator The numerator, for example the three in 'one and three sevenths' 215 * @param denominator The denominator, for example the seven in 'one and three sevenths' 216 * @return A new fraction instance 217 * @throws ArithmeticException Thrown if the denominator is {@code zero}. 218 * @throws ArithmeticException Thrown if the denominator is negative. 219 * @throws ArithmeticException Thrown if the numerator is negative. 220 * @throws ArithmeticException Thrown if the resulting numerator exceeds {@code Integer.MAX_VALUE}. 221 */ 222 public static Fraction getFraction(final int whole, final int numerator, final int denominator) { 223 checkDenominator(denominator); 224 if (denominator < 0) { 225 throw new ArithmeticException("The denominator must not be negative"); 226 } 227 if (numerator < 0) { 228 throw new ArithmeticException("The numerator must not be negative"); 229 } 230 final long numeratorValue; 231 if (whole < 0) { 232 numeratorValue = whole * (long) denominator - numerator; 233 } else { 234 numeratorValue = whole * (long) denominator + numerator; 235 } 236 if (numeratorValue < Integer.MIN_VALUE || numeratorValue > Integer.MAX_VALUE) { 237 throw new ArithmeticException("Numerator too large to represent as an Integer."); 238 } 239 return new Fraction((int) numeratorValue, denominator); 240 } 241 242 /** 243 * Gets a Fraction from a {@link String}. 244 * <p> 245 * The formats accepted are: 246 * </p> 247 * <ol> 248 * <li>{@code double} String containing a dot</li> 249 * <li>{@code "X Y/Z"}</li> 250 * <li>{@code "Y/Z"}</li> 251 * <li>{@code "X"} (a simple whole number)</li> 252 * </ol> 253 * <p> 254 * and a {@code .} 255 * </p> 256 * 257 * @param str The string to parse, must not be {@code null} 258 * @return The new {@link Fraction} instance 259 * @throws NullPointerException Thrown if the string is {@code null} 260 * @throws NumberFormatException Thrown if the number format is invalid, or if the string is well-formed but its value cannot be represented as a 261 * {@code Fraction}: a zero denominator such as {@code "1/0"}, a value outside the range of an {@code int} such as 262 * {@code "9999999999.5"}, or a mixed number whose combined numerator overflows. For those unrepresentable values, the causal 263 * {@link ArithmeticException} is preserved as the {@link Throwable#getCause() cause}. 264 */ 265 public static Fraction getFraction(final String str) { 266 Objects.requireNonNull(str, "str"); 267 // parse double format 268 int pos = str.indexOf('.'); 269 if (pos >= 0) { 270 final double value = Double.parseDouble(str); 271 try { 272 return getFraction(value); 273 } catch (final ArithmeticException e) { 274 throw toNumberFormatException(str, e); 275 } 276 } 277 278 // parse X Y/Z format 279 pos = str.indexOf(' '); 280 if (pos > 0) { 281 final int whole = Integer.parseInt(str.substring(0, pos)); 282 final String remainder = str.substring(pos + 1); 283 pos = remainder.indexOf('/'); 284 if (pos < 0) { 285 throw new NumberFormatException("The fraction could not be parsed as the format X Y/Z"); 286 } 287 final int numer = Integer.parseInt(remainder.substring(0, pos)); 288 final int denom = Integer.parseInt(remainder.substring(pos + 1)); 289 try { 290 return getFraction(whole, numer, denom); 291 } catch (final ArithmeticException e) { 292 throw toNumberFormatException(str, e); 293 } 294 } 295 296 // parse Y/Z format 297 pos = str.indexOf('/'); 298 if (pos < 0) { 299 // simple whole number 300 return getFraction(Integer.parseInt(str), 1); 301 } 302 final int numer = Integer.parseInt(str.substring(0, pos)); 303 final int denom = Integer.parseInt(str.substring(pos + 1)); 304 try { 305 return getFraction(numer, denom); 306 } catch (final ArithmeticException e) { 307 throw toNumberFormatException(str, e); 308 } 309 } 310 311 /** 312 * Gets a reduced {@link Fraction} instance with the 2 parts of a fraction Y/Z. 313 * <p> 314 * For example, if the input parameters represent 2/4, then the created fraction will be 1/2. 315 * </p> 316 * 317 * <p> 318 * Any negative signs are resolved to be on the numerator. 319 * </p> 320 * 321 * @param numerator The numerator, for example the three in 'three sevenths' 322 * @param denominator The denominator, for example the seven in 'three sevenths' 323 * @return A new fraction instance, with the numerator and denominator reduced 324 * @throws ArithmeticException Thrown if the denominator is {@code zero}, or the reduced numerator or positive denominator cannot be represented as an 325 * {@code int}. 326 */ 327 public static Fraction getReducedFraction(int numerator, int denominator) { 328 checkDenominator(denominator); 329 if (numerator == 0) { 330 return ZERO; // normalize zero. 331 } 332 // Reduce common powers of two before sign normalization to avoid negating Integer.MIN_VALUE. 333 while ((numerator & 1) == 0 && (denominator & 1) == 0) { 334 numerator /= 2; 335 denominator /= 2; 336 } 337 if (denominator < 0) { 338 if (numerator == Integer.MIN_VALUE || denominator == Integer.MIN_VALUE) { 339 throw new ArithmeticException("overflow: can't negate"); 340 } 341 numerator = -numerator; 342 denominator = -denominator; 343 } 344 // simplify fraction. 345 final int gcd = greatestCommonDivisor(numerator, denominator); 346 numerator /= gcd; 347 denominator /= gcd; 348 return new Fraction(numerator, denominator); 349 } 350 351 /** 352 * Gets the greatest common divisor of the absolute value of 353 * two numbers, using the "binary gcd" method which avoids 354 * division and modulo operations. See Knuth 4.5.2 algorithm B. 355 * This algorithm is due to Josef Stein (1961). 356 * 357 * @param u A non-zero number 358 * @param v A non-zero number 359 * @return The greatest common divisor, never zero 360 */ 361 private static int greatestCommonDivisor(int u, int v) { 362 // From Commons Math: 363 if (u == 0 || v == 0) { 364 if (u == Integer.MIN_VALUE || v == Integer.MIN_VALUE) { 365 throw new ArithmeticException("overflow: gcd is 2^31"); 366 } 367 return Math.abs(u) + Math.abs(v); 368 } 369 // if either operand is abs 1, return 1: 370 if (Math.abs(u) == 1 || Math.abs(v) == 1) { 371 return 1; 372 } 373 // keep u and v negative, as negative integers range down to 374 // -2^31, while positive numbers can only be as large as 2^31-1 375 // (i.e. we can't necessarily negate a negative number without 376 // overflow) 377 if (u > 0) { 378 u = -u; 379 } // make u negative 380 if (v > 0) { 381 v = -v; 382 } // make v negative 383 // B1. [Find power of 2] 384 int k = 0; 385 while ((u & 1) == 0 && (v & 1) == 0 && k < 31) { // while u and v are both even... 386 u /= 2; 387 v /= 2; 388 k++; // cast out twos. 389 } 390 if (k == 31) { 391 throw new ArithmeticException("overflow: gcd is 2^31"); 392 } 393 // B2. Initialize: u and v have been divided by 2^k and at least 394 // one is odd. 395 int t = (u & 1) == 1 ? v : -(u / 2)/* B3 */; 396 // t negative: u was odd, v may be even (t replaces v) 397 // t positive: u was even, v is odd (t replaces u) 398 do { 399 /* assert u<0 && v<0; */ 400 // B4/B3: cast out twos from t. 401 while ((t & 1) == 0) { // while t is even. 402 t /= 2; // cast out twos 403 } 404 // B5 [reset max(u,v)] 405 if (t > 0) { 406 u = -t; 407 } else { 408 v = t; 409 } 410 // B6/B3. at this point both u and v should be odd. 411 t = (v - u) / 2; 412 // |u| larger: t positive (replace u) 413 // |v| larger: t negative (replace v) 414 } while (t != 0); 415 return -u * (1 << k); // gcd is u*2^k 416 } 417 418 private static int hash(final int value1, final int value2) { 419 return Objects.hash(value1, value2); 420 } 421 422 /** 423 * Multiplies two integers, checking for overflow. 424 * 425 * @param x A factor 426 * @param y A factor 427 * @return The product {@code x*y} 428 * @throws ArithmeticException Thrown if the result cannot be represented as an int. 429 */ 430 private static int mulAndCheck(final int x, final int y) { 431 final long m = (long) x * (long) y; 432 if (m < Integer.MIN_VALUE || m > Integer.MAX_VALUE) { 433 throw new ArithmeticException("overflow: mul"); 434 } 435 return (int) m; 436 } 437 438 /** 439 * Multiplies two non-negative integers, checking for overflow. 440 * 441 * @param x A non-negative factor 442 * @param y A non-negative factor 443 * @return The product {@code x*y} 444 * @throws ArithmeticException Thrown if the result cannot be represented as an int. 445 */ 446 private static int mulPosAndCheck(final int x, final int y) { 447 /* assert x>=0 && y>=0; */ 448 final long m = (long) x * (long) y; 449 if (m > Integer.MAX_VALUE) { 450 throw new ArithmeticException("overflow: mulPos"); 451 } 452 return (int) m; 453 } 454 455 /** 456 * Converts an {@link ArithmeticException} raised while parsing a string into the {@link NumberFormatException} that 457 * {@link #getFraction(String)} documents, preserving the original exception as the cause. 458 * 459 * @param str The string being parsed. 460 * @param cause The arithmetic failure: a zero denominator or a value outside the range of an {@code int}. 461 * @return The exception for the caller to throw, never {@code null}. 462 */ 463 private static NumberFormatException toNumberFormatException(final String str, final ArithmeticException cause) { 464 final NumberFormatException nfe = new NumberFormatException("The fraction could not be parsed from '" + str + "': " + cause.getMessage()); 465 nfe.initCause(cause); 466 return nfe; 467 } 468 469 /** 470 * The numerator number part of the fraction (the three in three sevenths). 471 */ 472 private final int numerator; 473 474 /** 475 * The denominator number part of the fraction (the seven in three sevenths). 476 */ 477 private final int denominator; 478 479 /** 480 * Cached output hashCode (class is immutable). 481 */ 482 private final int hashCode; 483 484 /** 485 * Cached output toString (class is immutable). 486 */ 487 private transient String toString; 488 489 /** 490 * Cached output toProperString (class is immutable). 491 */ 492 private transient String toProperString; 493 494 /** 495 * Constructs a {@link Fraction} instance with the 2 parts 496 * of a fraction Y/Z. 497 * 498 * @param numerator The numerator, for example the three in 'three sevenths' 499 * @param denominator The denominator, for example the seven in 'three sevenths' 500 */ 501 private Fraction(final int numerator, final int denominator) { 502 this.numerator = numerator; 503 this.denominator = denominator; 504 this.hashCode = hash(denominator, numerator); 505 } 506 507 /** 508 * Gets a fraction that is the positive equivalent of this one. 509 * <p> 510 * More precisely: {@code (fraction >= 0 ? this : -fraction)} 511 * </p> 512 * <p> 513 * The returned fraction is not reduced. 514 * </p> 515 * 516 * @return {@code this} if it is positive, or a new positive fraction instance with the opposite signed numerator 517 */ 518 public Fraction abs() { 519 if (numerator >= 0) { 520 return this; 521 } 522 return negate(); 523 } 524 525 /** 526 * Adds the value of this fraction to another, returning the result in reduced form. 527 * The algorithm follows Knuth, 4.5.1. 528 * 529 * @param fraction The fraction to add, must not be {@code null} 530 * @return A {@link Fraction} instance with the resulting values 531 * @throws NullPointerException Thrown if the fraction is {@code null}. 532 * @throws ArithmeticException Thrown if the resulting numerator or denominator exceeds {@code Integer.MAX_VALUE}. 533 */ 534 public Fraction add(final Fraction fraction) { 535 return addSub(fraction, true /* add */); 536 } 537 538 /** 539 * Implements add and subtract using the algorithm described in <a href="https://www-cs-faculty.stanford.edu/~knuth/taocp.html"> 540 * The Art of Computer Programming (TAOCP)</a> 4.5.1 by Donald Knuth. 541 * 542 * @param fraction The fraction to subtract, must not be {@code null} 543 * @param isAdd true to add, false to subtract 544 * @return A {@link Fraction} instance with the resulting values 545 * @throws IllegalArgumentException Thrown if the fraction is {@code null}. 546 * @throws ArithmeticException Thrown if the resulting numerator or denominator 547 * cannot be represented in an {@code int}. 548 */ 549 private Fraction addSub(final Fraction fraction, final boolean isAdd) { 550 Objects.requireNonNull(fraction, "fraction"); 551 // zero is identity for addition. 552 if (numerator == 0) { 553 return isAdd ? fraction.reduce() : fraction.reduce().negate(); 554 } 555 if (fraction.numerator == 0) { 556 return reduce(); 557 } 558 // Knuth 4.5.1 assumes operands in lowest terms and this class does not reduce on 559 // construction, so reduce both first, as multiplyBy does. 560 final int thisGcd = greatestCommonDivisor(numerator, denominator); 561 final int thatGcd = greatestCommonDivisor(fraction.numerator, fraction.denominator); 562 final int thisNumerator = numerator / thisGcd; 563 final int thisDenominator = denominator / thisGcd; 564 final int thatNumerator = fraction.numerator / thatGcd; 565 final int thatDenominator = fraction.denominator / thatGcd; 566 // if denominators are randomly distributed, d1 will be 1 about 61% 567 // of the time. 568 final int d1 = greatestCommonDivisor(thisDenominator, thatDenominator); 569 if (d1 == 1) { 570 // result is ((u*v' +/- u'v) / u'v') 571 // the int cross products u*v' and u'*v can overflow even when the reduced result 572 // fits an int, so widen to long and let Math narrow the final numerator back. 573 final long uvp = (long) thisNumerator * thatDenominator; 574 final long upv = (long) thatNumerator * thisDenominator; 575 final long t = isAdd ? Math.addExact(uvp, upv) : Math.subtractExact(uvp, upv); 576 return new Fraction(Math.toIntExact(t), mulPosAndCheck(thisDenominator, thatDenominator)); 577 } 578 // the quantity 't' requires 65 bits of precision; see knuth 4.5.1 579 // exercise 7. we're going to use a BigInteger. 580 // t = u(v'/d1) +/- v(u'/d1) 581 final BigInteger uvp = BigInteger.valueOf(thisNumerator).multiply(BigInteger.valueOf(thatDenominator / d1)); 582 final BigInteger upv = BigInteger.valueOf(thatNumerator).multiply(BigInteger.valueOf(thisDenominator / d1)); 583 final BigInteger t = isAdd ? uvp.add(upv) : uvp.subtract(upv); 584 // but d2 doesn't need extra precision because 585 // d2 = gcd(t,d1) = gcd(t mod d1, d1) 586 final int tmodd1 = t.mod(BigInteger.valueOf(d1)).intValue(); 587 final int d2 = tmodd1 == 0 ? d1 : greatestCommonDivisor(tmodd1, d1); 588 589 // result is (t/d2) / (u'/d1)(v'/d2) 590 final BigInteger w = t.divide(BigInteger.valueOf(d2)); 591 if (w.bitLength() > 31) { 592 throw new ArithmeticException("overflow: numerator too large after multiply"); 593 } 594 return new Fraction(w.intValue(), mulPosAndCheck(thisDenominator / d1, thatDenominator / d2)); 595 } 596 597 /** 598 * Compares this object to another based on size. 599 * <p> 600 * Note: this class has a natural ordering that is inconsistent with equals, because, for example, equals treats 1/2 and 2/4 as different, whereas compareTo 601 * treats them as equal. 602 * </p> 603 * 604 * @param other The object to compare to 605 * @return -1 if this is less, 0 if equal, +1 if greater 606 * @throws ClassCastException Thrown if the object is not a {@link Fraction}. 607 * @throws NullPointerException Thrown if the object is {@code null}. 608 */ 609 @Override 610 public int compareTo(final Fraction other) { 611 if (this == other || numerator == other.numerator && denominator == other.denominator) { 612 return 0; 613 } 614 615 // otherwise see which is less 616 final long first = (long) numerator * (long) other.denominator; 617 final long second = (long) other.numerator * (long) denominator; 618 return Long.compare(first, second); 619 } 620 621 /** 622 * Divide the value of this fraction by another. 623 * 624 * @param fraction The fraction to divide by, must not be {@code null} 625 * @return A {@link Fraction} instance with the resulting values 626 * @throws NullPointerException Thrown if the fraction is {@code null}. 627 * @throws ArithmeticException Thrown if the fraction to divide by is zero. 628 * @throws ArithmeticException Thrown if the resulting numerator or denominator exceeds {@code Integer.MAX_VALUE}. 629 */ 630 public Fraction divideBy(final Fraction fraction) { 631 Objects.requireNonNull(fraction, "fraction"); 632 if (fraction.numerator == 0) { 633 throw new ArithmeticException("The fraction to divide by must not be zero"); 634 } 635 return multiplyBy(fraction.invert()); 636 } 637 638 /** 639 * Gets the fraction as a {@code double}. This calculates the fraction 640 * as the numerator divided by denominator. 641 * 642 * @return The fraction as a {@code double} 643 */ 644 @Override 645 public double doubleValue() { 646 return (double) numerator / (double) denominator; 647 } 648 649 /** 650 * Compares this fraction to another object to test if they are equal. 651 * <p> 652 * To be equal, both values must be equal. Thus 2/4 is not equal to 1/2. 653 * </p> 654 * 655 * @param obj The reference object with which to compare 656 * @return {@code true} if this object is equal 657 */ 658 @Override 659 public boolean equals(final Object obj) { 660 if (obj == this) { 661 return true; 662 } 663 if (!(obj instanceof Fraction)) { 664 return false; 665 } 666 final Fraction other = (Fraction) obj; 667 return getNumerator() == other.getNumerator() && getDenominator() == other.getDenominator(); 668 } 669 670 /** 671 * Gets the fraction as a {@code float}. This calculates the fraction 672 * as the numerator divided by denominator. 673 * 674 * @return The fraction as a {@code float} 675 */ 676 @Override 677 public float floatValue() { 678 return (float) numerator / (float) denominator; 679 } 680 681 /** 682 * Gets the denominator part of the fraction. 683 * 684 * @return The denominator fraction part 685 */ 686 public int getDenominator() { 687 return denominator; 688 } 689 690 /** 691 * Gets the numerator part of the fraction. 692 * <p> 693 * This method may return a value greater than the denominator, an improper fraction, such as the seven in 7/4. 694 * </p> 695 * 696 * @return The numerator fraction part 697 */ 698 public int getNumerator() { 699 return numerator; 700 } 701 702 /** 703 * Gets the proper numerator, always positive. 704 * <p> 705 * An improper fraction 7/4 can be resolved into a proper one, 1 3/4. This method returns the 3 from the proper fraction. 706 * </p> 707 * 708 * <p> 709 * If the fraction is negative such as -7/4, it can be resolved into -1 3/4, so this method returns the positive proper numerator, 3. 710 * </p> 711 * 712 * @return The numerator fraction part of a proper fraction, always positive 713 */ 714 public int getProperNumerator() { 715 return Math.abs(numerator % denominator); 716 } 717 718 /** 719 * Gets the proper whole part of the fraction. 720 * <p> 721 * An improper fraction 7/4 can be resolved into a proper one, 1 3/4. This method returns the 1 from the proper fraction. 722 * </p> 723 * 724 * <p> 725 * If the fraction is negative such as -7/4, it can be resolved into -1 3/4, so this method returns the positive whole part -1. 726 * </p> 727 * 728 * @return The whole fraction part of a proper fraction, that includes the sign 729 */ 730 public int getProperWhole() { 731 return numerator / denominator; 732 } 733 734 /** 735 * Gets a hashCode for the fraction. 736 * 737 * @return A hash code value for this object 738 */ 739 @Override 740 public int hashCode() { 741 return hashCode; 742 } 743 744 /** 745 * Gets the fraction as an {@code int}. This returns the whole number 746 * part of the fraction. 747 * 748 * @return The whole number fraction part 749 */ 750 @Override 751 public int intValue() { 752 return numerator / denominator; 753 } 754 755 /** 756 * Gets a fraction that is the inverse (1/fraction) of this one. 757 * <p> 758 * The returned fraction is not reduced. 759 * </p> 760 * 761 * @return A new fraction instance with the numerator and denominator inverted. 762 * @throws ArithmeticException Thrown if the fraction represents zero. 763 */ 764 public Fraction invert() { 765 if (numerator == 0) { 766 throw new ArithmeticException("Unable to invert zero."); 767 } 768 if (numerator == Integer.MIN_VALUE) { 769 throw new ArithmeticException("overflow: can't negate numerator"); 770 } 771 if (numerator < 0) { 772 return new Fraction(-denominator, -numerator); 773 } 774 return new Fraction(denominator, numerator); 775 } 776 777 /** 778 * Gets the fraction as a {@code long}. This returns the whole number 779 * part of the fraction. 780 * 781 * @return The whole number fraction part 782 */ 783 @Override 784 public long longValue() { 785 return (long) numerator / denominator; 786 } 787 788 /** 789 * Multiplies the value of this fraction by another, returning the 790 * result in reduced form. 791 * 792 * @param fraction The fraction to multiply by, must not be {@code null} 793 * @return A {@link Fraction} instance with the resulting values 794 * @throws NullPointerException Thrown if the fraction is {@code null}. 795 * @throws ArithmeticException Thrown if the resulting numerator or denominator exceeds {@code Integer.MAX_VALUE}. 796 */ 797 public Fraction multiplyBy(final Fraction fraction) { 798 Objects.requireNonNull(fraction, "fraction"); 799 if (numerator == 0 || fraction.numerator == 0) { 800 return ZERO; 801 } 802 // knuth 4.5.1 803 // make sure we don't overflow unless the result *must* overflow. 804 // Reduce both operands first: the cross-gcd below cancels the cross terms only, so a 805 // factor shared inside an unreduced operand survives into the product and can overflow 806 // an int even when the reduced result fits. 807 final int thisGcd = greatestCommonDivisor(numerator, denominator); 808 final int thatGcd = greatestCommonDivisor(fraction.numerator, fraction.denominator); 809 final int thisNumerator = numerator / thisGcd; 810 final int thisDenominator = denominator / thisGcd; 811 final int thatNumerator = fraction.numerator / thatGcd; 812 final int thatDenominator = fraction.denominator / thatGcd; 813 final int d1 = greatestCommonDivisor(thisNumerator, thatDenominator); 814 final int d2 = greatestCommonDivisor(thatNumerator, thisDenominator); 815 return getReducedFraction(mulAndCheck(thisNumerator / d1, thatNumerator / d2), mulPosAndCheck(thisDenominator / d2, thatDenominator / d1)); 816 } 817 818 /** 819 * Gets a fraction that is the negative (-fraction) of this one. 820 * <p> 821 * The returned fraction is not reduced. 822 * </p> 823 * 824 * @return A new fraction instance with the opposite signed numerator 825 */ 826 public Fraction negate() { 827 // the positive range is one smaller than the negative range of an int. 828 if (numerator == Integer.MIN_VALUE) { 829 throw new ArithmeticException("overflow: too large to negate"); 830 } 831 return new Fraction(-numerator, denominator); 832 } 833 834 /** 835 * Gets a fraction that is raised to the passed in power. 836 * <p> 837 * The returned fraction is in reduced form. 838 * </p> 839 * 840 * @param power The power to raise the fraction to 841 * @return {@code this} if the power is one, {@link #ONE} if the power is zero (even if the fraction equals ZERO) or a new fraction instance raised to the 842 * appropriate power 843 * @throws ArithmeticException Thrown if the resulting numerator or denominator exceeds {@code Integer.MAX_VALUE}. 844 */ 845 public Fraction pow(final int power) { 846 if (power == 1) { 847 return this; 848 } 849 if (power == 0) { 850 return ONE; 851 } 852 if (power < 0) { 853 if (power == Integer.MIN_VALUE) { // MIN_VALUE can't be negated. 854 return invert().pow(2).pow(-(power / 2)); 855 } 856 return invert().pow(-power); 857 } 858 final Fraction f = multiplyBy(this); 859 if (power % 2 == 0) { // if even... 860 return f.pow(power / 2); 861 } 862 return f.pow(power / 2).multiplyBy(this); 863 } 864 865 /** 866 * Validates the cached hashCode after deserialization. Throws a {@link InvalidObjectException} when the stored hashCode does not match the canonical hash 867 * of the deserialized numerator/denominator. 868 * 869 * @param in See {@link Serializable}. 870 * @throws IOException Thrown as described in {@link Serializable}. 871 * @throws ClassNotFoundException Thrown as described in {@link Serializable}. 872 * @throws InvalidObjectException Thrown if the hashCode doesn't match the denominator and numerator. 873 */ 874 private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { 875 in.defaultReadObject(); 876 checkDenominator(denominator); 877 if (hashCode != hash(denominator, numerator)) { 878 throw new InvalidObjectException("Fraction hashCode does not match numerator/denominator."); 879 } 880 } 881 882 /** 883 * Reduce the fraction to the smallest values for the numerator and denominator, returning the result. 884 * <p> 885 * For example, if this fraction represents 2/4, then the result will be 1/2. 886 * </p> 887 * 888 * @return A new reduced fraction instance, or this if no simplification possible 889 */ 890 public Fraction reduce() { 891 if (numerator == 0) { 892 return equals(ZERO) ? this : ZERO; 893 } 894 final int gcd = greatestCommonDivisor(Math.abs(numerator), denominator); 895 if (gcd == 1) { 896 return this; 897 } 898 return getFraction(numerator / gcd, denominator / gcd); 899 } 900 901 /** 902 * Subtracts the value of another fraction from the value of this one, 903 * returning the result in reduced form. 904 * 905 * @param fraction The fraction to subtract, must not be {@code null} 906 * @return A {@link Fraction} instance with the resulting values 907 * @throws NullPointerException Thrown if the fraction is {@code null}. 908 * @throws ArithmeticException Thrown if the resulting numerator or denominator 909 * cannot be represented in an {@code int}. 910 */ 911 public Fraction subtract(final Fraction fraction) { 912 return addSub(fraction, false /* subtract */); 913 } 914 915 /** 916 * Gets the fraction as a proper {@link String} in the format X Y/Z. 917 * <p> 918 * The format used in '<em>wholeNumber</em> <em>numerator</em>/<em>denominator</em>'. If the whole number is zero it will be omitted. If the numerator is 919 * zero, only the whole number is returned. 920 * </p> 921 * 922 * @return A {@link String} form of the fraction 923 */ 924 public String toProperString() { 925 if (toProperString == null) { 926 if (numerator == 0) { 927 toProperString = "0"; 928 } else if (numerator == denominator) { 929 toProperString = "1"; 930 } else if (numerator == -1 * denominator) { 931 toProperString = "-1"; 932 } else if ((numerator > 0 ? -numerator : numerator) < -denominator) { 933 // note that we do the magnitude comparison test above with 934 // NEGATIVE (not positive) numbers, since negative numbers 935 // have a larger range. otherwise numerator == Integer.MIN_VALUE 936 // is handled incorrectly. 937 final int properNumerator = getProperNumerator(); 938 if (properNumerator == 0) { 939 toProperString = Integer.toString(getProperWhole()); 940 } else { 941 toProperString = getProperWhole() + " " + properNumerator + "/" + getDenominator(); 942 } 943 } else { 944 toProperString = getNumerator() + "/" + getDenominator(); 945 } 946 } 947 return toProperString; 948 } 949 950 /** 951 * Gets the fraction as a {@link String}. 952 * <p> 953 * The format used is '<em>numerator</em>/<em>denominator</em>' always. 954 * </p> 955 * 956 * @return A {@link String} form of the fraction 957 */ 958 @Override 959 public String toString() { 960 if (toString == null) { 961 toString = getNumerator() + "/" + getDenominator(); 962 } 963 return toString; 964 } 965}