source: src/main/java/agents/anac/y2019/harddealer/math3/fraction/BigFraction.java

Last change on this file was 204, checked in by Katsuhide Fujita, 5 years ago

Fixed errors of ANAC2019 agents

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