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 * http://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.numbers.fraction; 018 019import java.io.Serializable; 020import org.apache.commons.numbers.core.ArithmeticUtils; 021import org.apache.commons.numbers.core.NativeOperators; 022 023/** 024 * Representation of a rational number. 025 */ 026public final class Fraction 027 extends Number 028 implements Comparable<Fraction>, 029 NativeOperators<Fraction>, 030 Serializable { 031 /** A fraction representing "1". */ 032 public static final Fraction ONE = new Fraction(1, 1); 033 /** A fraction representing "0". */ 034 public static final Fraction ZERO = new Fraction(0, 1); 035 /** Serializable version identifier. */ 036 private static final long serialVersionUID = 20190701L; 037 /** The default epsilon used for convergence. */ 038 private static final double DEFAULT_EPSILON = 1e-5; 039 /** The denominator of this fraction reduced to lowest terms. */ 040 private final int denominator; 041 /** The numerator of this fraction reduced to lowest terms. */ 042 private final int numerator; 043 044 /** 045 * Create a fraction given the double value and either the maximum error 046 * allowed or the maximum number of denominator digits. 047 * <p> 048 * 049 * NOTE: This constructor is called with EITHER 050 * - a valid epsilon value and the maxDenominator set to Integer.MAX_VALUE 051 * (that way the maxDenominator has no effect). 052 * OR 053 * - a valid maxDenominator value and the epsilon value set to zero 054 * (that way epsilon only has effect if there is an exact match before 055 * the maxDenominator value is reached). 056 * </p><p> 057 * 058 * It has been done this way so that the same code can be (re)used for both 059 * scenarios. However this could be confusing to users if it were part of 060 * the public API and this constructor should therefore remain PRIVATE. 061 * </p> 062 * 063 * See JIRA issue ticket MATH-181 for more details: 064 * https://issues.apache.org/jira/browse/MATH-181 065 * 066 * @param value the double value to convert to a fraction. 067 * @param epsilon maximum error allowed. The resulting fraction is 068 * within {@code epsilon} of {@code value}, in absolute terms. 069 * @param maxDenominator maximum denominator value allowed. 070 * @param maxIterations maximum number of convergents 071 * @throws ArithmeticException if the continued fraction failed 072 * to converge. 073 */ 074 private Fraction(double value, double epsilon, int maxDenominator, int maxIterations) { 075 final long overflow = Integer.MAX_VALUE; 076 double r0 = value; 077 long a0 = (long)Math.floor(r0); 078 if (Math.abs(a0) > overflow) { 079 throw new FractionException(FractionException.ERROR_CONVERSION, value, a0, 1L); 080 } 081 082 // check for (almost) integer arguments, which should not go to iterations. 083 if (Math.abs(a0 - value) < epsilon) { 084 this.numerator = (int) a0; 085 this.denominator = 1; 086 return; 087 } 088 089 long p0 = 1; 090 long q0 = 0; 091 long p1 = a0; 092 long q1 = 1; 093 094 long p2 = 0; 095 long q2 = 1; 096 097 int n = 0; 098 boolean stop = false; 099 do { 100 ++n; 101 final double r1 = 1.0 / (r0 - a0); 102 final long a1 = (long)Math.floor(r1); 103 p2 = (a1 * p1) + p0; 104 q2 = (a1 * q1) + q0; 105 106 if (Math.abs(p2) > overflow || 107 Math.abs(q2) > overflow) { 108 // in maxDenominator mode, if the last fraction was very close to the actual value 109 // q2 may overflow in the next iteration; in this case return the last one. 110 if (epsilon == 0.0 && 111 Math.abs(q1) < maxDenominator) { 112 break; 113 } 114 throw new FractionException(FractionException.ERROR_CONVERSION, value, p2, q2); 115 } 116 117 final double convergent = (double)p2 / (double)q2; 118 if (n < maxIterations && 119 Math.abs(convergent - value) > epsilon && 120 q2 < maxDenominator) { 121 p0 = p1; 122 p1 = p2; 123 q0 = q1; 124 q1 = q2; 125 a0 = a1; 126 r0 = r1; 127 } else { 128 stop = true; 129 } 130 } while (!stop); 131 132 if (n >= maxIterations) { 133 throw new FractionException(FractionException.ERROR_CONVERSION, value, maxIterations); 134 } 135 136 if (q2 < maxDenominator) { 137 this.numerator = (int) p2; 138 this.denominator = (int) q2; 139 } else { 140 this.numerator = (int) p1; 141 this.denominator = (int) q1; 142 } 143 } 144 145 /** 146 * Constructs an instance. 147 * 148 * @param num Numerator. 149 * @param den Nenominator. 150 * @throws ArithmeticException if the denominator is {@code zero} 151 * or if integer overflow occurs. 152 */ 153 private Fraction(int num, int den) { 154 if (den == 0) { 155 throw new ArithmeticException("division by zero"); 156 } 157 158 if (num == den) { 159 numerator = 1; 160 denominator = 1; 161 } else { 162 // If num and den are both 2^-31, or if one is 0 and the other is 2^-31, 163 // the calculation of the gcd below will fail. Ensure that this does not 164 // happen by dividing both by 2 in case both are even. 165 if (((num | den) & 1) == 0) { 166 num >>= 1; 167 den >>= 1; 168 } 169 170 // Reduce numerator and denominator by greatest common divisor. 171 final int d = ArithmeticUtils.gcd(num, den); 172 if (d > 1) { 173 num /= d; 174 den /= d; 175 } 176 177 numerator = num; 178 denominator = den; 179 } 180 } 181 182 /** 183 * Creates an instance. 184 * 185 * @param value Value to convert to a fraction. 186 * @throws ArithmeticException if the continued fraction failed to 187 * converge. 188 * @return a new instance. 189 */ 190 public static Fraction from(double value) { 191 return from(value, DEFAULT_EPSILON, 100); 192 } 193 194 /** 195 * Create a fraction given the double value and maximum error allowed. 196 * 197 * <p> 198 * References: 199 * <ul> 200 * <li><a href="http://mathworld.wolfram.com/ContinuedFraction.html"> 201 * Continued Fraction</a> equations (11) and (22)-(26)</li> 202 * </ul> 203 * 204 * @param value the double value to convert to a fraction. 205 * @param epsilon maximum error allowed. The resulting fraction is within 206 * {@code epsilon} of {@code value}, in absolute terms. 207 * @param maxIterations maximum number of convergents 208 * @throws ArithmeticException if the continued fraction failed to 209 * converge. 210 * @return a new instance. 211 */ 212 public static Fraction from(double value, double epsilon, int maxIterations) { 213 return new Fraction(value, epsilon, Integer.MAX_VALUE, maxIterations); 214 } 215 216 /** 217 * Creates an instance. 218 * 219 * <p> 220 * References: 221 * <ul> 222 * <li><a href="http://mathworld.wolfram.com/ContinuedFraction.html"> 223 * Continued Fraction</a> equations (11) and (22)-(26)</li> 224 * </ul> 225 * 226 * @param value the double value to convert to a fraction. 227 * @param maxDenominator The maximum allowed value for denominator 228 * @throws ArithmeticException if the continued fraction failed to 229 * converge. 230 * @return a new instance. 231 */ 232 public static Fraction from(double value, int maxDenominator) { 233 return new Fraction(value, 0, maxDenominator, 100); 234 } 235 236 /** 237 * Creates an instance. 238 * The fraction is {@code num / 1}. 239 * 240 * @param num Numerator. 241 * @return a new instance. 242 */ 243 public static Fraction of(int num) { 244 return of(num, 1); 245 } 246 247 /** 248 * Return a fraction given the numerator and denominator. 249 * The fraction is reduced to lowest terms. 250 * 251 * @param num Numerator. 252 * @param den Denominator. 253 * @throws ArithmeticException if the denominator is {@code zero} 254 * or if integer overflow occurs. 255 * @return a new instance. 256 */ 257 public static Fraction of(int num, int den) { 258 return new Fraction(num, den); 259 } 260 261 /** 262 * Returns the absolute value of this fraction. 263 * 264 * @return the absolute value. 265 */ 266 public Fraction abs() { 267 return signum() >= 0 ? 268 this : 269 negate(); 270 } 271 272 /** 273 * Compares this object to another based on size. 274 * 275 * @param other Object to compare to. 276 * @return -1 if this is less than {@code object}, +1 if this is greater 277 * than {@code object}, 0 if they are equal. 278 */ 279 @Override 280 public int compareTo(Fraction other) { 281 return Long.compare(((long) numerator) * other.denominator, 282 ((long) denominator) * other.numerator); 283 } 284 285 /** 286 * Retrieves the {@code double} value closest to this fraction. 287 * This calculates the fraction as numerator divided by denominator. 288 * 289 * @return the fraction as a {@code double}. 290 */ 291 @Override 292 public double doubleValue() { 293 return (double) numerator / (double) denominator; 294 } 295 296 /** 297 * Test for the equality of two fractions. 298 * If the lowest term numerator and denominators are the same for 299 * both fractions, the two fractions are considered to be equal. 300 * @param other Fraction to test for equality with. 301 * @return {@code true} if the two fractions are equal, {@code false} 302 * otherwise. 303 */ 304 @Override 305 public boolean equals(Object other) { 306 if (this == other) { 307 return true; 308 } 309 310 if (other instanceof Fraction) { 311 // Since fractions are always in lowest terms, numerators and 312 // denominators can be compared directly for equality. 313 final Fraction rhs = (Fraction) other; 314 if (signum() == rhs.signum()) { 315 return Math.abs(numerator) == Math.abs(rhs.numerator) && 316 Math.abs(denominator) == Math.abs(rhs.denominator); 317 } else { 318 return false; 319 } 320 } 321 322 return false; 323 } 324 325 /** 326 * Retrieves the {@code float} value closest to this fraction. 327 * This calculates the fraction as numerator divided by denominator. 328 * 329 * @return the fraction as {@code float}. 330 */ 331 @Override 332 public float floatValue() { 333 return (float) doubleValue(); 334 } 335 336 /** 337 * @return the denominator. 338 */ 339 public int getDenominator() { 340 return denominator; 341 } 342 343 /** 344 * @return the numerator. 345 */ 346 public int getNumerator() { 347 return numerator; 348 } 349 350 /** {@inheritDoc} */ 351 @Override 352 public int hashCode() { 353 return 37 * (37 * 17 + numerator) + denominator; 354 } 355 356 /** 357 * Retrieves the whole number part of the fraction. 358 * 359 * @return the largest {@code int} value that is not larger than 360 * this fraction. 361 */ 362 @Override 363 public int intValue() { 364 return (int) doubleValue(); 365 } 366 367 /** 368 * Retrieves the whole number part of the fraction. 369 * 370 * @return the largest {@code long} value that is not larger than 371 * this fraction. 372 */ 373 @Override 374 public long longValue() { 375 return (long) doubleValue(); 376 } 377 378 /** 379 * Retrieves the sign of this fraction. 380 * 381 * @return -1 if the value is strictly negative, 1 if it is strictly 382 * positive, 0 if it is 0. 383 */ 384 public int signum() { 385 if ((numerator > 0 && denominator > 0) || 386 (numerator < 0 && denominator < 0)) { 387 return 1; 388 } else if (numerator == 0) { 389 return 0; 390 } else { 391 return -1; 392 } 393 } 394 395 /** 396 * Computes the additive inverse of this fraction. 397 * 398 * @return the opposite. 399 */ 400 @Override 401 public Fraction negate() { 402 return numerator == Integer.MIN_VALUE ? 403 new Fraction(numerator, -denominator) : 404 new Fraction(-numerator, denominator); 405 } 406 407 /** 408 * Computes the multiplicative inverse of this fraction. 409 * 410 * @return the reciprocal. 411 */ 412 @Override 413 public Fraction reciprocal() { 414 return new Fraction(denominator, numerator); 415 } 416 417 /** 418 * Adds the value of this fraction to another, returning the result 419 * in reduced form. 420 * The algorithm follows Knuth, 4.5.1. 421 * 422 * @param fraction Fraction to add. 423 * @return a new instance. 424 * @throws ArithmeticException if the resulting numerator or denominator 425 * cannot be represented in an {@code int}. 426 */ 427 @Override 428 public Fraction add(Fraction fraction) { 429 return addSub(fraction, true /* add */); 430 } 431 432 /** 433 * Adds an integer to the fraction. 434 * 435 * @param i Value to add. 436 * @return {@code this + i}. 437 */ 438 public Fraction add(final int i) { 439 return new Fraction(numerator + i * denominator, denominator); 440 } 441 442 /** 443 * Subtracts the value of another fraction from the value of this one, 444 * returning the result in reduced form. 445 * 446 * @param fraction Fraction to subtract. 447 * @return a new instance. 448 * @throws ArithmeticException if the resulting numerator or denominator 449 * cannot be represented in an {@code int}. 450 */ 451 @Override 452 public Fraction subtract(Fraction fraction) { 453 return addSub(fraction, false /* subtract */); 454 } 455 456 /** 457 * Subtracts an integer from this fraction. 458 * 459 * @param i Value to subtract. 460 * @return {@code this - i}. 461 */ 462 public Fraction subtract(final int i) { 463 return new Fraction(numerator - i * denominator, denominator); 464 } 465 466 /** 467 * Implements add and subtract using algorithm described in Knuth 4.5.1. 468 * 469 * @param fraction Fraction to add or subtract. 470 * @param isAdd Whether the operation is "add" or "subtract". 471 * @return a new instance. 472 * @throws ArithmeticException if the resulting numerator or denominator 473 * cannot be represented in an {@code int}. 474 */ 475 private Fraction addSub(Fraction fraction, boolean isAdd) { 476 // Zero is identity for addition. 477 if (numerator == 0) { 478 return isAdd ? fraction : fraction.negate(); 479 } 480 481 if (fraction.numerator == 0) { 482 return this; 483 } 484 485 /* 486 * Let the two fractions be u/u' and v/v', and d1 = gcd(u', v'). 487 * First, compute t, defined as: 488 * 489 * t = u(v'/d1) +/- v(u'/d1) 490 */ 491 final int d1 = ArithmeticUtils.gcd(denominator, fraction.denominator); 492 final long uvp = (long) numerator * (long) (fraction.denominator / d1); 493 final long upv = (long) fraction.numerator * (long) (denominator / d1); 494 495 /* 496 * The largest possible absolute value of a product of two ints is 2^62, 497 * which can only happen as a result of -2^31 * -2^31 = 2^62, so a 498 * product of -2^62 is not possible. It follows that (uvp - upv) cannot 499 * overflow, and (uvp + upv) could only overflow if uvp = upv = 2^62. 500 * But for this to happen, the terms u, v, v'/d1 and u'/d1 would all 501 * have to be -2^31, which is not possible because v'/d1 and u'/d1 502 * are necessarily coprime. 503 */ 504 final long t = isAdd ? uvp + upv : uvp - upv; 505 506 /* 507 * Because u is coprime to u' and v is coprime to v', t is necessarily 508 * coprime to both v'/d1 and u'/d1. However, it might have a common 509 * factor with d1. 510 */ 511 final long d2 = ArithmeticUtils.gcd(t, d1); 512 // result is (t/d2) / (u'/d1)(v'/d2) 513 return of(Math.toIntExact(t / d2), 514 Math.multiplyExact(denominator / d1, 515 fraction.denominator / (int) d2)); 516 } 517 518 /** 519 * Multiplies the value of this fraction by another, returning the 520 * result in reduced form. 521 * 522 * @param fraction Fraction to multiply by. 523 * @return a new instance. 524 * @throws ArithmeticException if the resulting numerator or denominator 525 * cannot be represented in an {@code int}. 526 */ 527 @Override 528 public Fraction multiply(Fraction fraction) { 529 if (numerator == 0 || 530 fraction.numerator == 0) { 531 return ZERO; 532 } 533 534 // knuth 4.5.1 535 // Make sure we don't overflow unless the result *must* overflow. 536 final int d1 = ArithmeticUtils.gcd(numerator, fraction.denominator); 537 final int d2 = ArithmeticUtils.gcd(fraction.numerator, denominator); 538 return of(Math.multiplyExact(numerator / d1, fraction.numerator / d2), 539 Math.multiplyExact(denominator / d2, fraction.denominator / d1)); 540 } 541 542 /** 543 * Multiplies the fraction by an integer. 544 * 545 * @param i Value to multiply by. 546 * @return {@code this * i}. 547 */ 548 @Override 549 public Fraction multiply(final int i) { 550 return multiply(of(i)); 551 } 552 553 /** 554 * Divides the value of this fraction by another. 555 * 556 * @param fraction Fraction to divide by. 557 * @return a new instance. 558 * @throws ArithmeticException if the fraction to divide by is zero 559 * or if the resulting numerator or denominator cannot be represented 560 * by an {@code int}. 561 */ 562 @Override 563 public Fraction divide(Fraction fraction) { 564 if (fraction.numerator == 0) { 565 throw new FractionException("the fraction to divide by must not be zero: {0}/{1}", 566 fraction.numerator, fraction.denominator); 567 } 568 569 return multiply(fraction.reciprocal()); 570 } 571 572 /** 573 * Divides the fraction by an integer. 574 * 575 * @param i Value to divide by. 576 * @return {@code this * i}. 577 */ 578 public Fraction divide(final int i) { 579 return divide(of(i)); 580 } 581 582 /** 583 * @param n Power. 584 * @return <code>this<sup>n</sup></code>. 585 */ 586 @Override 587 public Fraction pow(final int n) { 588 if (n == 0) { 589 return ONE; 590 } 591 if (numerator == 0) { 592 return this; 593 } 594 595 return n < 0 ? 596 new Fraction(ArithmeticUtils.pow(denominator, -n), 597 ArithmeticUtils.pow(numerator, -n)) : 598 new Fraction(ArithmeticUtils.pow(numerator, n), 599 ArithmeticUtils.pow(denominator, n)); 600 } 601 602 /** {@inheritDoc} */ 603 @Override 604 public String toString() { 605 final String str; 606 if (denominator == 1) { 607 str = Integer.toString(numerator); 608 } else if (numerator == 0) { 609 str = "0"; 610 } else { 611 str = numerator + " / " + denominator; 612 } 613 return str; 614 } 615 616 /** {@inheritDoc} */ 617 @Override 618 public Fraction zero() { 619 return ZERO; 620 } 621 622 /** {@inheritDoc} */ 623 @Override 624 public Fraction one() { 625 return ONE; 626 } 627 628 /** 629 * Parses a string that would be produced by {@link #toString()} 630 * and instantiates the corresponding object. 631 * 632 * @param s String representation. 633 * @return an instance. 634 * @throws NumberFormatException if the string does not conform to the 635 * specification. 636 */ 637 public static Fraction parse(String s) { 638 final int slashLoc = s.indexOf('/'); 639 // if no slash, parse as single number 640 if (slashLoc == -1) { 641 return Fraction.of(Integer.parseInt(s.trim())); 642 } else { 643 final int num = Integer.parseInt(s.substring(0, slashLoc).trim()); 644 final int denom = Integer.parseInt(s.substring(slashLoc + 1).trim()); 645 return of(num, denom); 646 } 647 } 648}