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 * https://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
18 /*
19 * This is not the original file distributed by the Apache Software Foundation
20 * It has been modified by the Hipparchus project
21 */
22 package org.hipparchus.fraction;
23
24 import java.io.Serializable;
25 import java.math.BigDecimal;
26 import java.math.BigInteger;
27 import java.math.RoundingMode;
28 import java.util.function.Function;
29 import java.util.stream.Stream;
30
31 import org.hipparchus.FieldElement;
32 import org.hipparchus.exception.LocalizedCoreFormats;
33 import org.hipparchus.exception.MathIllegalArgumentException;
34 import org.hipparchus.exception.MathIllegalStateException;
35 import org.hipparchus.exception.MathRuntimeException;
36 import org.hipparchus.exception.NullArgumentException;
37 import org.hipparchus.fraction.ConvergentsIterator.ConvergenceStep;
38 import org.hipparchus.util.ArithmeticUtils;
39 import org.hipparchus.util.FastMath;
40 import org.hipparchus.util.MathUtils;
41 import org.hipparchus.util.Pair;
42 import org.hipparchus.util.Precision;
43
44 /**
45 * Representation of a rational number without any overflow. This class is
46 * immutable.
47 *
48 */
49 public class BigFraction
50 extends Number
51 implements FieldElement<BigFraction>, Comparable<BigFraction>, Serializable {
52
53 /** A fraction representing "2 / 1". */
54 public static final BigFraction TWO = new BigFraction(2);
55
56 /** A fraction representing "1". */
57 public static final BigFraction ONE = new BigFraction(1);
58
59 /** A fraction representing "0". */
60 public static final BigFraction ZERO = new BigFraction(0);
61
62 /** A fraction representing "-1 / 1". */
63 public static final BigFraction MINUS_ONE = new BigFraction(-1);
64
65 /** A fraction representing "4/5". */
66 public static final BigFraction FOUR_FIFTHS = new BigFraction(4, 5);
67
68 /** A fraction representing "1/5". */
69 public static final BigFraction ONE_FIFTH = new BigFraction(1, 5);
70
71 /** A fraction representing "1/2". */
72 public static final BigFraction ONE_HALF = new BigFraction(1, 2);
73
74 /** A fraction representing "1/4". */
75 public static final BigFraction ONE_QUARTER = new BigFraction(1, 4);
76
77 /** A fraction representing "1/3". */
78 public static final BigFraction ONE_THIRD = new BigFraction(1, 3);
79
80 /** A fraction representing "3/5". */
81 public static final BigFraction THREE_FIFTHS = new BigFraction(3, 5);
82
83 /** A fraction representing "3/4". */
84 public static final BigFraction THREE_QUARTERS = new BigFraction(3, 4);
85
86 /** A fraction representing "2/5". */
87 public static final BigFraction TWO_FIFTHS = new BigFraction(2, 5);
88
89 /** A fraction representing "2/4". */
90 public static final BigFraction TWO_QUARTERS = new BigFraction(2, 4);
91
92 /** A fraction representing "2/3". */
93 public static final BigFraction TWO_THIRDS = new BigFraction(2, 3);
94
95 /** Serializable version identifier. */
96 private static final long serialVersionUID = -5630213147331578515L;
97
98 /** <code>BigInteger</code> representation of 100. */
99 private static final BigInteger ONE_HUNDRED = BigInteger.valueOf(100);
100
101 /** Convert a convergence step to the corresponding double fraction. */
102 private static final Function<ConvergenceStep, BigFraction> STEP_TO_FRACTION = //
103 s -> new BigFraction(s.getNumerator(), s.getDenominator());
104
105 /** The numerator. */
106 private final BigInteger numerator;
107
108 /** The denominator. */
109 private final BigInteger denominator;
110
111 /**
112 * <p>
113 * Create a {@link BigFraction} equivalent to the passed {@code BigInteger}, ie
114 * "num / 1".
115 * </p>
116 *
117 * @param num
118 * the numerator.
119 */
120 public BigFraction(final BigInteger num) {
121 this(num, BigInteger.ONE);
122 }
123
124 /**
125 * Create a {@link BigFraction} given the numerator and denominator as
126 * {@code BigInteger}. The {@link BigFraction} is reduced to lowest terms.
127 *
128 * @param num the numerator, must not be {@code null}.
129 * @param den the denominator, must not be {@code null}.
130 * @throws MathIllegalArgumentException if the denominator is zero.
131 * @throws NullArgumentException if either of the arguments is null
132 */
133 public BigFraction(BigInteger num, BigInteger den) {
134 MathUtils.checkNotNull(num, LocalizedCoreFormats.NUMERATOR);
135 MathUtils.checkNotNull(den, LocalizedCoreFormats.DENOMINATOR);
136 if (den.signum() == 0) {
137 throw new MathIllegalArgumentException(LocalizedCoreFormats.ZERO_DENOMINATOR);
138 }
139 if (num.signum() == 0) {
140 numerator = BigInteger.ZERO;
141 denominator = BigInteger.ONE;
142 } else {
143
144 // reduce numerator and denominator by greatest common denominator
145 final BigInteger gcd = num.gcd(den);
146 if (BigInteger.ONE.compareTo(gcd) < 0) {
147 num = num.divide(gcd);
148 den = den.divide(gcd);
149 }
150
151 // move sign to numerator
152 if (den.signum() == -1) {
153 num = num.negate();
154 den = den.negate();
155 }
156
157 // store the values in the final fields
158 numerator = num;
159 denominator = den;
160
161 }
162 }
163
164 /**
165 * Create a fraction given the double value.
166 * <p>
167 * This constructor behaves <em>differently</em> from
168 * {@link #BigFraction(double, double, int)}. It converts the double value
169 * exactly, considering its internal bits representation. This works for all
170 * values except NaN and infinities and does not requires any loop or
171 * convergence threshold.
172 * </p>
173 * <p>
174 * Since this conversion is exact and since double numbers are sometimes
175 * approximated, the fraction created may seem strange in some cases. For example,
176 * calling <code>new BigFraction(1.0 / 3.0)</code> does <em>not</em> create
177 * the fraction 1/3, but the fraction 6004799503160661 / 18014398509481984
178 * because the double number passed to the constructor is not exactly 1/3
179 * (this number cannot be stored exactly in IEEE754).
180 * </p>
181 * @see #BigFraction(double, double, int)
182 * @param value the double value to convert to a fraction.
183 * @exception MathIllegalArgumentException if value is NaN or infinite
184 */
185 public BigFraction(final double value) throws MathIllegalArgumentException {
186 if (Double.isNaN(value)) {
187 throw new MathIllegalArgumentException(LocalizedCoreFormats.NAN_VALUE_CONVERSION);
188 }
189 if (Double.isInfinite(value)) {
190 throw new MathIllegalArgumentException(LocalizedCoreFormats.INFINITE_VALUE_CONVERSION);
191 }
192
193 // compute m and k such that value = m * 2^k
194 final long bits = Double.doubleToLongBits(value);
195 final long sign = bits & 0x8000000000000000L;
196 final long exponent = bits & 0x7ff0000000000000L;
197 long m = bits & 0x000fffffffffffffL;
198 if (exponent != 0) {
199 // this was a normalized number, add the implicit most significant bit
200 m |= 0x0010000000000000L;
201 }
202 if (sign != 0) {
203 m = -m;
204 }
205 int k = ((int) (exponent >> 52)) - 1075;
206 while (((m & 0x001ffffffffffffeL) != 0) && ((m & 0x1) == 0)) {
207 m >>= 1;
208 ++k;
209 }
210
211 if (k < 0) {
212 numerator = BigInteger.valueOf(m);
213 denominator = BigInteger.ZERO.flipBit(-k);
214 } else {
215 numerator = BigInteger.valueOf(m).multiply(BigInteger.ZERO.flipBit(k));
216 denominator = BigInteger.ONE;
217 }
218
219 }
220
221 /**
222 * Create a fraction given the double value and maximum error allowed.
223 * <p>* References:</p>
224 * <ul>
225 * <li><a href="http://mathworld.wolfram.com/ContinuedFraction.html">
226 * Continued Fraction</a> equations (11) and (22)-(26)</li>
227 * </ul>
228 *
229 * @param value
230 * the double value to convert to a fraction.
231 * @param epsilon
232 * maximum error allowed. The resulting fraction is within
233 * <code>epsilon</code> of <code>value</code>, in absolute terms.
234 * @param maxIterations
235 * maximum number of convergents.
236 * @throws MathIllegalStateException
237 * if the continued fraction failed to converge.
238 * @see #BigFraction(double)
239 */
240 public BigFraction(final double value, final double epsilon,
241 final int maxIterations)
242 throws MathIllegalStateException {
243 ConvergenceStep converged = ConvergentsIterator.convergent(value, maxIterations, s -> {
244 final double quotient = s.getFractionValue();
245 return Precision.equals(quotient, value, 1) || FastMath.abs(quotient - value) < epsilon;
246 }).getKey();
247 if (FastMath.abs(converged.getFractionValue() - value) < epsilon) {
248 this.numerator = BigInteger.valueOf(converged.getNumerator());
249 this.denominator = BigInteger.valueOf(converged.getDenominator());
250 } else {
251 throw new MathIllegalStateException(LocalizedCoreFormats.FAILED_FRACTION_CONVERSION,
252 value, maxIterations);
253 }
254 }
255
256 /**
257 * Create a fraction given the double value and maximum denominator.
258 * <p>* References:</p>
259 * <ul>
260 * <li><a href="http://mathworld.wolfram.com/ContinuedFraction.html">
261 * Continued Fraction</a> equations (11) and (22)-(26)</li>
262 * </ul>
263 *
264 * @param value
265 * the double value to convert to a fraction.
266 * @param maxDenominator
267 * The maximum allowed value for denominator.
268 * @throws MathIllegalStateException
269 * if the continued fraction failed to converge.
270 */
271 public BigFraction(final double value, final long maxDenominator)
272 throws MathIllegalStateException {
273 final int maxIterations = 100;
274 ConvergenceStep[] lastValid = new ConvergenceStep[1];
275 ConvergentsIterator.convergent(value, maxIterations, s -> {
276 if (s.getDenominator() < maxDenominator) {
277 lastValid[0] = s;
278 }
279 return Precision.equals(s.getFractionValue(), value, 1);
280 });
281 if (lastValid[0] != null) {
282 this.numerator = BigInteger.valueOf(lastValid[0].getNumerator());
283 this.denominator = BigInteger.valueOf(lastValid[0].getDenominator());
284 } else {
285 throw new MathIllegalStateException(LocalizedCoreFormats.FAILED_FRACTION_CONVERSION,
286 value, maxIterations);
287 }
288 }
289
290 /**
291 * <p>
292 * Create a {@link BigFraction} equivalent to the passed {@code int}, ie
293 * "num / 1".
294 * </p>
295 *
296 * @param num
297 * the numerator.
298 */
299 public BigFraction(final int num) {
300 this(BigInteger.valueOf(num), BigInteger.ONE);
301 }
302
303 /**
304 * <p>
305 * Create a {@link BigFraction} given the numerator and denominator as simple
306 * {@code int}. The {@link BigFraction} is reduced to lowest terms.
307 * </p>
308 *
309 * @param num
310 * the numerator.
311 * @param den
312 * the denominator.
313 */
314 public BigFraction(final int num, final int den) {
315 this(BigInteger.valueOf(num), BigInteger.valueOf(den));
316 }
317
318 /**
319 * <p>
320 * Create a {@link BigFraction} equivalent to the passed long, ie "num / 1".
321 * </p>
322 *
323 * @param num
324 * the numerator.
325 */
326 public BigFraction(final long num) {
327 this(BigInteger.valueOf(num), BigInteger.ONE);
328 }
329
330 /**
331 * <p>
332 * Create a {@link BigFraction} given the numerator and denominator as simple
333 * {@code long}. The {@link BigFraction} is reduced to lowest terms.
334 * </p>
335 *
336 * @param num
337 * the numerator.
338 * @param den
339 * the denominator.
340 */
341 public BigFraction(final long num, final long den) {
342 this(BigInteger.valueOf(num), BigInteger.valueOf(den));
343 }
344
345 /**
346 * A test to determine if a series of fractions has converged.
347 */
348 @FunctionalInterface
349 public interface ConvergenceTest {
350 /**
351 * Evaluates if the fraction formed by {@code numerator/denominator} satisfies
352 * this convergence test.
353 *
354 * @param numerator the numerator
355 * @param denominator the denominator
356 * @return if this convergence test is satisfied
357 */
358 boolean test(long numerator, long denominator); // NOPMD - this is not a Junit test, PMD false positive here
359 }
360
361 /** Generate a {@link Stream stream} of convergents from a real number.
362 * @param value value to approximate
363 * @param maxConvergents maximum number of convergents.
364 * @return stream of {@link BigFraction} convergents approximating {@code value}
365 * @since 2.1
366 */
367 public static Stream<BigFraction> convergents(final double value, final int maxConvergents) {
368 return ConvergentsIterator.convergents(value, maxConvergents).map(STEP_TO_FRACTION);
369 }
370
371 /**
372 * Returns the last element of the series of convergent-steps to approximate the
373 * given value.
374 * <p>
375 * The series terminates either at the first step that satisfies the given
376 * {@code convergenceTest} or after at most {@code maxConvergents} elements. The
377 * returned Pair consists of that terminal {@link BigFraction} and a
378 * {@link Boolean} that indicates if it satisfies the given convergence tests.
379 * If the returned pair's value is {@code false} the element at position
380 * {@code maxConvergents} was examined but failed to satisfy the
381 * {@code convergenceTest}. A caller can then decide to accept the result
382 * nevertheless or to discard it. This method is usually faster than
383 * {@link #convergents(double, int)} if only the terminal element is of
384 * interest.
385 *
386 * @param value value to approximate
387 * @param maxConvergents maximum number of convergents to examine
388 * @param convergenceTest the test if the series has converged at a step
389 * @return the pair of last element of the series of convergents and a boolean
390 * indicating if that element satisfies the specified convergent test
391 */
392 public static Pair<BigFraction, Boolean> convergent(double value, int maxConvergents,
393 ConvergenceTest convergenceTest) {
394 Pair<ConvergenceStep, Boolean> converged = ConvergentsIterator.convergent(value, maxConvergents,
395 s -> convergenceTest.test(s.getNumerator(), s.getDenominator()));
396 return Pair.create(STEP_TO_FRACTION.apply(converged.getKey()), converged.getValue());
397 }
398
399 /** {@inheritDoc} */
400 @Override
401 public double getReal() {
402 return doubleValue();
403 }
404
405 /**
406 * <p>
407 * Creates a {@code BigFraction} instance with the 2 parts of a fraction
408 * Y/Z.
409 * </p>
410 *
411 * <p>
412 * Any negative signs are resolved to be on the numerator.
413 * </p>
414 *
415 * @param numerator
416 * the numerator, for example the three in 'three sevenths'.
417 * @param denominator
418 * the denominator, for example the seven in 'three sevenths'.
419 * @return a new fraction instance, with the numerator and denominator
420 * reduced.
421 * @throws ArithmeticException
422 * if the denominator is <code>zero</code>.
423 */
424 public static BigFraction getReducedFraction(final int numerator,
425 final int denominator) {
426 if (numerator == 0) {
427 return ZERO; // normalize zero.
428 }
429
430 return new BigFraction(numerator, denominator);
431 }
432
433 /**
434 * <p>
435 * Returns the absolute value of this {@link BigFraction}.
436 * </p>
437 *
438 * @return the absolute value as a {@link BigFraction}.
439 */
440 public BigFraction abs() {
441 return (numerator.signum() == 1) ? this : negate();
442 }
443
444 /** Check if a fraction is an integer.
445 * @return true of fraction is an integer
446 */
447 public boolean isInteger() {
448 return denominator.equals(BigInteger.ONE);
449 }
450
451 /** Returns the signum function of this {@link BigFraction}.
452 * <p>
453 * The return value is -1 if the specified value is negative;
454 * 0 if the specified value is zero; and 1 if the specified value is positive.
455 * </p>
456 * @return the signum function of this {@link BigFraction}
457 * @since 1.7
458 */
459 public int signum() {
460 return numerator.signum();
461 }
462
463 /**
464 * <p>
465 * Adds the value of this fraction to the passed {@link BigInteger},
466 * returning the result in reduced form.
467 * </p>
468 *
469 * @param bg
470 * the {@link BigInteger} to add, must'nt be <code>null</code>.
471 * @return a {@code BigFraction} instance with the resulting values.
472 * @throws NullArgumentException
473 * if the {@link BigInteger} is <code>null</code>.
474 */
475 public BigFraction add(final BigInteger bg) throws NullArgumentException {
476 MathUtils.checkNotNull(bg);
477
478 if (numerator.signum() == 0) {
479 return new BigFraction(bg);
480 }
481 if (bg.signum() == 0) {
482 return this;
483 }
484
485 return new BigFraction(numerator.add(denominator.multiply(bg)), denominator);
486 }
487
488 /**
489 * <p>
490 * Adds the value of this fraction to the passed {@code integer}, returning
491 * the result in reduced form.
492 * </p>
493 *
494 * @param i
495 * the {@code integer} to add.
496 * @return a {@code BigFraction} instance with the resulting values.
497 */
498 public BigFraction add(final int i) {
499 return add(BigInteger.valueOf(i));
500 }
501
502 /**
503 * <p>
504 * Adds the value of this fraction to the passed {@code long}, returning
505 * the result in reduced form.
506 * </p>
507 *
508 * @param l
509 * the {@code long} to add.
510 * @return a {@code BigFraction} instance with the resulting values.
511 */
512 public BigFraction add(final long l) {
513 return add(BigInteger.valueOf(l));
514 }
515
516 /**
517 * <p>
518 * Adds the value of this fraction to another, returning the result in
519 * reduced form.
520 * </p>
521 *
522 * @param fraction
523 * the {@link BigFraction} to add, must not be <code>null</code>.
524 * @return a {@link BigFraction} instance with the resulting values.
525 * @throws NullArgumentException if the {@link BigFraction} is {@code null}.
526 */
527 @Override
528 public BigFraction add(final BigFraction fraction) {
529 MathUtils.checkNotNull(fraction, LocalizedCoreFormats.FRACTION);
530 if (fraction.numerator.signum() == 0) {
531 return this;
532 }
533 if (numerator.signum() == 0) {
534 return fraction;
535 }
536
537 BigInteger num;
538 BigInteger den;
539 if (denominator.equals(fraction.denominator)) {
540 num = numerator.add(fraction.numerator);
541 den = denominator;
542 } else {
543 num = (numerator.multiply(fraction.denominator)).add((fraction.numerator).multiply(denominator));
544 den = denominator.multiply(fraction.denominator);
545 }
546
547 if (num.signum() == 0) {
548 return ZERO;
549 }
550
551 return new BigFraction(num, den);
552
553 }
554
555 /**
556 * <p>
557 * Gets the fraction as a <code>BigDecimal</code>. This calculates the
558 * fraction as the numerator divided by denominator.
559 * </p>
560 *
561 * @return the fraction as a <code>BigDecimal</code>.
562 * @throws ArithmeticException
563 * if the exact quotient does not have a terminating decimal
564 * expansion.
565 * @see BigDecimal
566 */
567 public BigDecimal bigDecimalValue() {
568 return new BigDecimal(numerator).divide(new BigDecimal(denominator));
569 }
570
571 /**
572 * <p>
573 * Gets the fraction as a <code>BigDecimal</code> following the passed
574 * rounding mode. This calculates the fraction as the numerator divided by
575 * denominator.
576 * </p>
577 *
578 * @param roundingMode
579 * rounding mode to apply. see {@link BigDecimal} constants.
580 * @return the fraction as a <code>BigDecimal</code>.
581 * @throws IllegalArgumentException
582 * if {@code roundingMode} does not represent a valid rounding
583 * mode.
584 * @see BigDecimal
585 */
586 public BigDecimal bigDecimalValue(final RoundingMode roundingMode) {
587 return new BigDecimal(numerator).divide(new BigDecimal(denominator), roundingMode);
588 }
589
590 /**
591 * <p>
592 * Gets the fraction as a <code>BigDecimal</code> following the passed scale
593 * and rounding mode. This calculates the fraction as the numerator divided
594 * by denominator.
595 * </p>
596 *
597 * @param scale
598 * scale of the <code>BigDecimal</code> quotient to be returned.
599 * see {@link BigDecimal} for more information.
600 * @param roundingMode
601 * rounding mode to apply. see {@link BigDecimal} constants.
602 * @return the fraction as a <code>BigDecimal</code>.
603 * @see BigDecimal
604 */
605 public BigDecimal bigDecimalValue(final int scale, final RoundingMode roundingMode) {
606 return new BigDecimal(numerator).divide(new BigDecimal(denominator), scale, roundingMode);
607 }
608
609 /**
610 * <p>
611 * Compares this object to another based on size.
612 * </p>
613 *
614 * @param object
615 * the object to compare to, must not be <code>null</code>.
616 * @return -1 if this is less than {@code object}, +1 if this is greater
617 * than {@code object}, 0 if they are equal.
618 * @see java.lang.Comparable#compareTo(java.lang.Object)
619 */
620 @Override
621 public int compareTo(final BigFraction object) {
622 int lhsSigNum = numerator.signum();
623 int rhsSigNum = object.numerator.signum();
624
625 if (lhsSigNum != rhsSigNum) {
626 return (lhsSigNum > rhsSigNum) ? 1 : -1;
627 }
628 if (lhsSigNum == 0) {
629 return 0;
630 }
631
632 BigInteger nOd = numerator.multiply(object.denominator);
633 BigInteger dOn = denominator.multiply(object.numerator);
634 return nOd.compareTo(dOn);
635 }
636
637 /**
638 * <p>
639 * Divide the value of this fraction by the passed {@code BigInteger},
640 * ie {@code this * 1 / bg}, returning the result in reduced form.
641 * </p>
642 *
643 * @param bg the {@code BigInteger} to divide by, must not be {@code null}
644 * @return a {@link BigFraction} instance with the resulting values
645 * @throws NullArgumentException if the {@code BigInteger} is {@code null}
646 * @throws MathRuntimeException if the fraction to divide by is zero
647 */
648 public BigFraction divide(final BigInteger bg) {
649 MathUtils.checkNotNull(bg);
650 if (bg.signum() == 0) {
651 throw new MathRuntimeException(LocalizedCoreFormats.ZERO_DENOMINATOR);
652 }
653 if (numerator.signum() == 0) {
654 return ZERO;
655 }
656 return new BigFraction(numerator, denominator.multiply(bg));
657 }
658
659 /**
660 * <p>
661 * Divide the value of this fraction by the passed {@code int}, ie
662 * {@code this * 1 / i}, returning the result in reduced form.
663 * </p>
664 *
665 * @param i the {@code int} to divide by
666 * @return a {@link BigFraction} instance with the resulting values
667 * @throws MathRuntimeException if the fraction to divide by is zero
668 */
669 public BigFraction divide(final int i) {
670 return divide(BigInteger.valueOf(i));
671 }
672
673 /**
674 * <p>
675 * Divide the value of this fraction by the passed {@code long}, ie
676 * {@code this * 1 / l}, returning the result in reduced form.
677 * </p>
678 *
679 * @param l the {@code long} to divide by
680 * @return a {@link BigFraction} instance with the resulting values
681 * @throws MathRuntimeException if the fraction to divide by is zero
682 */
683 public BigFraction divide(final long l) {
684 return divide(BigInteger.valueOf(l));
685 }
686
687 /**
688 * <p>
689 * Divide the value of this fraction by another, returning the result in
690 * reduced form.
691 * </p>
692 *
693 * @param fraction Fraction to divide by, must not be {@code null}.
694 * @return a {@link BigFraction} instance with the resulting values.
695 * @throws NullArgumentException if the {@code fraction} is {@code null}.
696 * @throws MathRuntimeException if the fraction to divide by is zero
697 */
698 @Override
699 public BigFraction divide(final BigFraction fraction) {
700 MathUtils.checkNotNull(fraction, LocalizedCoreFormats.FRACTION);
701 if (fraction.numerator.signum() == 0) {
702 throw new MathRuntimeException(LocalizedCoreFormats.ZERO_DENOMINATOR);
703 }
704 if (numerator.signum() == 0) {
705 return ZERO;
706 }
707
708 return multiply(fraction.reciprocal());
709 }
710
711 /**
712 * <p>
713 * Gets the fraction as a {@code double}. This calculates the fraction as
714 * the numerator divided by denominator.
715 * </p>
716 *
717 * @return the fraction as a {@code double}
718 * @see java.lang.Number#doubleValue()
719 */
720 @Override
721 public double doubleValue() {
722 double result = numerator.doubleValue() / denominator.doubleValue();
723 if (Double.isInfinite(result) || Double.isNaN(result)) {
724 // Numerator and/or denominator must be out of range:
725 // Calculate how far to shift them to put them in range.
726 int shift = FastMath.max(numerator.bitLength(),
727 denominator.bitLength()) - FastMath.getExponent(Double.MAX_VALUE);
728 result = numerator.shiftRight(shift).doubleValue() /
729 denominator.shiftRight(shift).doubleValue();
730 }
731 return result;
732 }
733
734 /**
735 * <p>
736 * Test for the equality of two fractions. If the lowest term numerator and
737 * denominators are the same for both fractions, the two fractions are
738 * considered to be equal.
739 * </p>
740 *
741 * @param other
742 * fraction to test for equality to this fraction, can be
743 * <code>null</code>.
744 * @return true if two fractions are equal, false if object is
745 * <code>null</code>, not an instance of {@link BigFraction}, or not
746 * equal to this fraction instance.
747 * @see java.lang.Object#equals(java.lang.Object)
748 */
749 @Override
750 public boolean equals(final Object other) {
751 boolean ret = false;
752
753 if (this == other) {
754 ret = true;
755 } else if (other instanceof BigFraction) {
756 BigFraction rhs = (BigFraction) other;
757 ret = numerator.equals(rhs.numerator) && denominator.equals(rhs.denominator);
758 }
759
760 return ret;
761 }
762
763 /**
764 * <p>
765 * Gets the fraction as a {@code float}. This calculates the fraction as
766 * the numerator divided by denominator.
767 * </p>
768 *
769 * @return the fraction as a {@code float}.
770 * @see java.lang.Number#floatValue()
771 */
772 @Override
773 public float floatValue() {
774 float result = numerator.floatValue() / denominator.floatValue();
775 if (Double.isNaN(result)) {
776 // Numerator and/or denominator must be out of range:
777 // Calculate how far to shift them to put them in range.
778 int shift = FastMath.max(numerator.bitLength(),
779 denominator.bitLength()) - FastMath.getExponent(Float.MAX_VALUE);
780 result = numerator.shiftRight(shift).floatValue() /
781 denominator.shiftRight(shift).floatValue();
782 }
783 return result;
784 }
785
786 /**
787 * {@link java.math.BigInteger} number least common multiple.
788 *
789 * @param i0 first number
790 * @param i1 second number
791 * @return Least Common Multiple of both numbers
792 * @since 3.1
793 */
794 private static BigInteger lcm(final BigInteger i0, final BigInteger i1) {
795 if (i0.signum() == 0 && i1.signum() == 0) {
796 return BigInteger.ZERO;
797 }
798 BigInteger a = i0.abs();
799 BigInteger b = i1.abs();
800 BigInteger gcd = i0.gcd(b);
801 return (a.multiply(b)).divide(gcd);
802 }
803
804 /**
805 * Rational number greatest common divisor.
806 *
807 * @param s fraction.
808 * @return gcd(this, s).
809 * @since 3.1
810 */
811 public BigFraction gcd(BigFraction s) {
812 if (s.isZero()) {
813 return this;
814 }
815 if (this.isZero()) {
816 return s;
817 }
818 BigInteger p = numerator.gcd(s.numerator);
819 BigInteger q = lcm(denominator, s.denominator);
820 return new BigFraction(p, q);
821 }
822
823 /**
824 * Rational number least common multiple.
825 *
826 * @param s fraction.
827 * @return lcm(this, s).
828 * @since 3.1
829 */
830 public BigFraction lcm(BigFraction s) {
831 if (s.isZero()) {
832 return ZERO;
833 }
834 if (this.isZero()) {
835 return ZERO;
836 }
837 return new BigFraction(lcm(numerator, s.numerator), denominator.gcd(s.denominator));
838 }
839
840 /**
841 * <p>
842 * Access the denominator as a <code>BigInteger</code>.
843 * </p>
844 *
845 * @return the denominator as a <code>BigInteger</code>.
846 */
847 public BigInteger getDenominator() {
848 return denominator;
849 }
850
851 /**
852 * <p>
853 * Access the denominator as a {@code int}.
854 * </p>
855 *
856 * @return the denominator as a {@code int}.
857 */
858 public int getDenominatorAsInt() {
859 return denominator.intValue();
860 }
861
862 /**
863 * <p>
864 * Access the denominator as a {@code long}.
865 * </p>
866 *
867 * @return the denominator as a {@code long}.
868 */
869 public long getDenominatorAsLong() {
870 return denominator.longValue();
871 }
872
873 /**
874 * <p>
875 * Access the numerator as a <code>BigInteger</code>.
876 * </p>
877 *
878 * @return the numerator as a <code>BigInteger</code>.
879 */
880 public BigInteger getNumerator() {
881 return numerator;
882 }
883
884 /**
885 * <p>
886 * Access the numerator as a {@code int}.
887 * </p>
888 *
889 * @return the numerator as a {@code int}.
890 */
891 public int getNumeratorAsInt() {
892 return numerator.intValue();
893 }
894
895 /**
896 * <p>
897 * Access the numerator as a {@code long}.
898 * </p>
899 *
900 * @return the numerator as a {@code long}.
901 */
902 public long getNumeratorAsLong() {
903 return numerator.longValue();
904 }
905
906 /**
907 * <p>
908 * Gets a hashCode for the fraction.
909 * </p>
910 *
911 * @return a hash code value for this object.
912 * @see java.lang.Object#hashCode()
913 */
914 @Override
915 public int hashCode() {
916 return 37 * (37 * 17 + numerator.hashCode()) + denominator.hashCode();
917 }
918
919 /**
920 * <p>
921 * Gets the fraction as an {@code int}. This returns the whole number part
922 * of the fraction.
923 * </p>
924 *
925 * @return the whole number fraction part.
926 * @see java.lang.Number#intValue()
927 */
928 @Override
929 public int intValue() {
930 return numerator.divide(denominator).intValue();
931 }
932
933 /**
934 * <p>
935 * Gets the fraction as a {@code long}. This returns the whole number part
936 * of the fraction.
937 * </p>
938 *
939 * @return the whole number fraction part.
940 * @see java.lang.Number#longValue()
941 */
942 @Override
943 public long longValue() {
944 return numerator.divide(denominator).longValue();
945 }
946
947 /**
948 * <p>
949 * Multiplies the value of this fraction by the passed
950 * <code>BigInteger</code>, returning the result in reduced form.
951 * </p>
952 *
953 * @param bg the {@code BigInteger} to multiply by.
954 * @return a {@code BigFraction} instance with the resulting values.
955 * @throws NullArgumentException if {@code bg} is {@code null}.
956 */
957 public BigFraction multiply(final BigInteger bg) {
958 MathUtils.checkNotNull(bg);
959 if (numerator.signum() == 0 || bg.signum() == 0) {
960 return ZERO;
961 }
962 return new BigFraction(bg.multiply(numerator), denominator);
963 }
964
965 /**
966 * <p>
967 * Multiply the value of this fraction by the passed {@code int}, returning
968 * the result in reduced form.
969 * </p>
970 *
971 * @param i
972 * the {@code int} to multiply by.
973 * @return a {@link BigFraction} instance with the resulting values.
974 */
975 @Override
976 public BigFraction multiply(final int i) {
977 if (i == 0 || numerator.signum() == 0) {
978 return ZERO;
979 }
980
981 return multiply(BigInteger.valueOf(i));
982 }
983
984 /**
985 * <p>
986 * Multiply the value of this fraction by the passed {@code long},
987 * returning the result in reduced form.
988 * </p>
989 *
990 * @param l
991 * the {@code long} to multiply by.
992 * @return a {@link BigFraction} instance with the resulting values.
993 */
994 public BigFraction multiply(final long l) {
995 if (l == 0 || numerator.signum() == 0) {
996 return ZERO;
997 }
998
999 return multiply(BigInteger.valueOf(l));
1000 }
1001
1002 /**
1003 * <p>
1004 * Multiplies the value of this fraction by another, returning the result in
1005 * reduced form.
1006 * </p>
1007 *
1008 * @param fraction Fraction to multiply by, must not be {@code null}.
1009 * @return a {@link BigFraction} instance with the resulting values.
1010 * @throws NullArgumentException if {@code fraction} is {@code null}.
1011 */
1012 @Override
1013 public BigFraction multiply(final BigFraction fraction) {
1014 MathUtils.checkNotNull(fraction, LocalizedCoreFormats.FRACTION);
1015 if (numerator.signum() == 0 ||
1016 fraction.numerator.signum() == 0) {
1017 return ZERO;
1018 }
1019 return new BigFraction(numerator.multiply(fraction.numerator),
1020 denominator.multiply(fraction.denominator));
1021 }
1022
1023 /**
1024 * <p>
1025 * Return the additive inverse of this fraction, returning the result in
1026 * reduced form.
1027 * </p>
1028 *
1029 * @return the negation of this fraction.
1030 */
1031 @Override
1032 public BigFraction negate() {
1033 return new BigFraction(numerator.negate(), denominator);
1034 }
1035
1036 /**
1037 * <p>
1038 * Gets the fraction percentage as a {@code double}. This calculates the
1039 * fraction as the numerator divided by denominator multiplied by 100.
1040 * </p>
1041 *
1042 * @return the fraction percentage as a {@code double}.
1043 */
1044 public double percentageValue() {
1045 return multiply(ONE_HUNDRED).doubleValue();
1046 }
1047
1048 /**
1049 * <p>
1050 * Returns a {@code BigFraction} whose value is
1051 * {@code (this<sup>exponent</sup>)}, returning the result in reduced form.
1052 * </p>
1053 *
1054 * @param exponent
1055 * exponent to which this {@code BigFraction} is to be
1056 * raised.
1057 * @return this<sup>exponent</sup>
1058 */
1059 public BigFraction pow(final int exponent) {
1060 if (exponent == 0) {
1061 return ONE;
1062 }
1063 if (numerator.signum() == 0) {
1064 return this;
1065 }
1066
1067 if (exponent < 0) {
1068 return new BigFraction(denominator.pow(-exponent), numerator.pow(-exponent));
1069 }
1070 return new BigFraction(numerator.pow(exponent), denominator.pow(exponent));
1071 }
1072
1073 /**
1074 * <p>
1075 * Returns a {@code BigFraction} whose value is
1076 * this<sup>exponent</sup>, returning the result in reduced form.
1077 * </p>
1078 *
1079 * @param exponent
1080 * exponent to which this {@code BigFraction} is to be raised.
1081 * @return this<sup>exponent</sup> as a {@code BigFraction}.
1082 */
1083 public BigFraction pow(final long exponent) {
1084 if (exponent == 0) {
1085 return ONE;
1086 }
1087 if (numerator.signum() == 0) {
1088 return this;
1089 }
1090
1091 if (exponent < 0) {
1092 return new BigFraction(ArithmeticUtils.pow(denominator, -exponent),
1093 ArithmeticUtils.pow(numerator, -exponent));
1094 }
1095 return new BigFraction(ArithmeticUtils.pow(numerator, exponent),
1096 ArithmeticUtils.pow(denominator, exponent));
1097 }
1098
1099 /**
1100 * <p>
1101 * Returns a {@code BigFraction} whose value is
1102 * this<sup>exponent</sup>, returning the result in reduced form.
1103 * </p>
1104 *
1105 * @param exponent
1106 * exponent to which this {@code BigFraction} is to be raised.
1107 * @return this<sup>exponent</sup> as a {@code BigFraction}.
1108 */
1109 public BigFraction pow(final BigInteger exponent) {
1110 if (exponent.signum() == 0) {
1111 return ONE;
1112 }
1113 if (numerator.signum() == 0) {
1114 return this;
1115 }
1116
1117 if (exponent.signum() == -1) {
1118 final BigInteger eNeg = exponent.negate();
1119 return new BigFraction(ArithmeticUtils.pow(denominator, eNeg),
1120 ArithmeticUtils.pow(numerator, eNeg));
1121 }
1122 return new BigFraction(ArithmeticUtils.pow(numerator, exponent),
1123 ArithmeticUtils.pow(denominator, exponent));
1124 }
1125
1126 /**
1127 * <p>
1128 * Returns a <code>double</code> whose value is
1129 * this<sup>exponent</sup>, returning the result in reduced form.
1130 * </p>
1131 *
1132 * @param exponent
1133 * exponent to which this {@code BigFraction} is to be raised.
1134 * @return this<sup>exponent</sup>
1135 */
1136 public double pow(final double exponent) {
1137 return FastMath.pow(numerator.doubleValue(), exponent) /
1138 FastMath.pow(denominator.doubleValue(), exponent);
1139 }
1140
1141 /**
1142 * <p>
1143 * Return the multiplicative inverse of this fraction.
1144 * </p>
1145 *
1146 * @return the reciprocal fraction.
1147 */
1148 @Override
1149 public BigFraction reciprocal() {
1150 return new BigFraction(denominator, numerator);
1151 }
1152
1153 /**
1154 * <p>
1155 * Reduce this {@code BigFraction} to its lowest terms.
1156 * </p>
1157 *
1158 * @return the reduced {@code BigFraction}. It doesn't change anything if
1159 * the fraction can be reduced.
1160 */
1161 public BigFraction reduce() {
1162 final BigInteger gcd = numerator.gcd(denominator);
1163
1164 if (BigInteger.ONE.compareTo(gcd) < 0) {
1165 return new BigFraction(numerator.divide(gcd), denominator.divide(gcd));
1166 } else {
1167 return this;
1168 }
1169 }
1170
1171 /**
1172 * <p>
1173 * Subtracts the value of an {@link BigInteger} from the value of this
1174 * {@code BigFraction}, returning the result in reduced form.
1175 * </p>
1176 *
1177 * @param bg the {@link BigInteger} to subtract, cannot be {@code null}.
1178 * @return a {@code BigFraction} instance with the resulting values.
1179 * @throws NullArgumentException if the {@link BigInteger} is {@code null}.
1180 */
1181 public BigFraction subtract(final BigInteger bg) {
1182 MathUtils.checkNotNull(bg);
1183 if (bg.signum() == 0) {
1184 return this;
1185 }
1186 if (numerator.signum() == 0) {
1187 return new BigFraction(bg.negate());
1188 }
1189
1190 return new BigFraction(numerator.subtract(denominator.multiply(bg)), denominator);
1191 }
1192
1193 /**
1194 * <p>
1195 * Subtracts the value of an {@code integer} from the value of this
1196 * {@code BigFraction}, returning the result in reduced form.
1197 * </p>
1198 *
1199 * @param i the {@code integer} to subtract.
1200 * @return a {@code BigFraction} instance with the resulting values.
1201 */
1202 public BigFraction subtract(final int i) {
1203 return subtract(BigInteger.valueOf(i));
1204 }
1205
1206 /**
1207 * <p>
1208 * Subtracts the value of a {@code long} from the value of this
1209 * {@code BigFraction}, returning the result in reduced form.
1210 * </p>
1211 *
1212 * @param l the {@code long} to subtract.
1213 * @return a {@code BigFraction} instance with the resulting values.
1214 */
1215 public BigFraction subtract(final long l) {
1216 return subtract(BigInteger.valueOf(l));
1217 }
1218
1219 /**
1220 * <p>
1221 * Subtracts the value of another fraction from the value of this one,
1222 * returning the result in reduced form.
1223 * </p>
1224 *
1225 * @param fraction {@link BigFraction} to subtract, must not be {@code null}.
1226 * @return a {@link BigFraction} instance with the resulting values
1227 * @throws NullArgumentException if the {@code fraction} is {@code null}.
1228 */
1229 @Override
1230 public BigFraction subtract(final BigFraction fraction) {
1231 MathUtils.checkNotNull(fraction, LocalizedCoreFormats.FRACTION);
1232 if (fraction.numerator.signum() == 0) {
1233 return this;
1234 }
1235 if (numerator.signum() == 0) {
1236 return fraction.negate();
1237 }
1238
1239 BigInteger num;
1240 BigInteger den;
1241 if (denominator.equals(fraction.denominator)) {
1242 num = numerator.subtract(fraction.numerator);
1243 den = denominator;
1244 } else {
1245 num = (numerator.multiply(fraction.denominator)).subtract((fraction.numerator).multiply(denominator));
1246 den = denominator.multiply(fraction.denominator);
1247 }
1248 return new BigFraction(num, den);
1249
1250 }
1251
1252 /**
1253 * <p>
1254 * Returns the <code>String</code> representing this fraction, ie
1255 * "num / dem" or just "num" if the denominator is one.
1256 * </p>
1257 *
1258 * @return a string representation of the fraction.
1259 * @see java.lang.Object#toString()
1260 */
1261 @Override
1262 public String toString() {
1263 if (BigInteger.ONE.equals(denominator)) {
1264 return numerator.toString();
1265 } else if (BigInteger.ZERO.equals(numerator)) {
1266 return "0";
1267 } else {
1268 return numerator + " / " + denominator;
1269 }
1270 }
1271
1272 /** {@inheritDoc} */
1273 @Override
1274 public BigFractionField getField() {
1275 return BigFractionField.getInstance();
1276 }
1277
1278 }