mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-25 06:50:46 +00:00
trunk contents moved to root
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* @(#)IntMath.java
|
||||
*
|
||||
* Copyright (c) 2002-2012 Werner Randelshofer, Goldau, Switzerland.
|
||||
* All rights reserved.
|
||||
*
|
||||
* You may not use, copy or modify this file, except in compliance with the
|
||||
* license agreement you entered into with Werner Randelshofer.
|
||||
* For details see accompanying license terms.
|
||||
*/
|
||||
|
||||
package org.monte.media.math;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Utility class for integer arithmetic.
|
||||
*
|
||||
* @author Werner Randelshofer
|
||||
* @version $Id: IntMath.java 299 2013-01-03 07:40:18Z werner $
|
||||
*/
|
||||
public class IntMath {
|
||||
|
||||
/** Creates a new instance of IntMath */
|
||||
public IntMath() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an int whose value is the greatest common divisor of
|
||||
* <tt>abs(a)</tt> and <tt>abs(b)</tt>. Returns 0 if
|
||||
* <tt>a==0 && b==0</tt>.
|
||||
*
|
||||
* @param a value with with the GCD is to be computed.
|
||||
* @param b value with with the GCD is to be computed.
|
||||
* @return <tt>GCD(a, b)</tt>
|
||||
*/
|
||||
public static int gcd(int a, int b) {
|
||||
// Quelle:
|
||||
// Herrmann, D. (1992). Algorithmen Arbeitsbuch.
|
||||
// Bonn, München Paris: Addison Wesley.
|
||||
// ggt6, Seite 63
|
||||
|
||||
a = Math.abs(a);
|
||||
b = Math.abs(b);
|
||||
|
||||
while (a > 0 && b > 0) {
|
||||
a = a % b;
|
||||
if (a > 0) b = b % a;
|
||||
}
|
||||
return a + b;
|
||||
}
|
||||
/**
|
||||
* Returns a long whose value is the greatest common divisor of
|
||||
* <tt>abs(a)</tt> and <tt>abs(b)</tt>. Returns 0 if
|
||||
* <tt>a==0 && b==0</tt>.
|
||||
*
|
||||
* @param a value with with the GCD is to be computed.
|
||||
* @param b value with with the GCD is to be computed.
|
||||
* @return <tt>GCD(a, b)</tt>
|
||||
*/
|
||||
public static long gcd(long a, long b) {
|
||||
// Quelle:
|
||||
// Herrmann, D. (1992). Algorithmen Arbeitsbuch.
|
||||
// Bonn, München Paris: Addison Wesley.
|
||||
// ggt6, Seite 63
|
||||
|
||||
a = Math.abs(a);
|
||||
b = Math.abs(b);
|
||||
|
||||
while (a > 0 && b > 0) {
|
||||
a = a % b;
|
||||
if (a > 0) b = b % a;
|
||||
}
|
||||
return a + b;
|
||||
}
|
||||
/**
|
||||
* Returns a long whose value is the greatest common divisor of
|
||||
* <tt>abs(a)</tt> and <tt>abs(b)</tt>. Returns 0 if
|
||||
* <tt>a==0 && b==0</tt>.
|
||||
*
|
||||
* @param a value with with the GCD is to be computed.
|
||||
* @param b value with with the GCD is to be computed.
|
||||
* @return <tt>GCD(a, b)</tt>
|
||||
*/
|
||||
public static BigInteger gcd(BigInteger a, BigInteger b) {
|
||||
// Quelle:
|
||||
// Herrmann, D. (1992). Algorithmen Arbeitsbuch.
|
||||
// Bonn, München Paris: Addison Wesley.
|
||||
// ggt6, Seite 63
|
||||
|
||||
a = a.abs();
|
||||
b = b.abs();
|
||||
|
||||
while (a.compareTo(BigInteger.ZERO) > 0 && b.compareTo(BigInteger.ZERO) > 0) {
|
||||
a = a.mod(b);
|
||||
if (a.compareTo(BigInteger.ZERO) > 0) b = b.mod(a);
|
||||
}
|
||||
return a.add(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an int whose value is the smallest common multiple of
|
||||
* <tt>abs(a)</tt> and <tt>abs(b)</tt>. Returns 0 if
|
||||
* <tt>a==0 || b==0</tt>.
|
||||
*
|
||||
* @param a value with with the SCM is to be computed.
|
||||
* @param b value with with the SCM is to be computed.
|
||||
* @return <tt>SCM(a, b)</tt>
|
||||
*/
|
||||
public static int scm(int a, int b) {
|
||||
// Quelle:
|
||||
// Herrmann, D. (1992). Algorithmen Arbeitsbuch.
|
||||
// Bonn, München Paris: Addison Wesley.
|
||||
// gill, Seite 141
|
||||
|
||||
if (a == 0 || b == 0) return 0;
|
||||
|
||||
a = Math.abs(a);
|
||||
b = Math.abs(b);
|
||||
|
||||
int u = a;
|
||||
int v = b;
|
||||
|
||||
while (a != b) {
|
||||
if (a < b) {
|
||||
b -= a;
|
||||
v += u;
|
||||
} else {
|
||||
a -= b;
|
||||
u += v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//return a; // gcd
|
||||
return (u + v) / 2; // scm
|
||||
}
|
||||
/**
|
||||
* Returns an int whose value is the smallest common multiple of
|
||||
* <tt>abs(a)</tt> and <tt>abs(b)</tt>. Returns 0 if
|
||||
* <tt>a==0 || b==0</tt>.
|
||||
*
|
||||
* @param a value with with the SCM is to be computed.
|
||||
* @param b value with with the SCM is to be computed.
|
||||
* @return <tt>SCM(a, b)</tt>
|
||||
*/
|
||||
public static long scm(long a, long b) {
|
||||
// Quelle:
|
||||
// Herrmann, D. (1992). Algorithmen Arbeitsbuch.
|
||||
// Bonn, München Paris: Addison Wesley.
|
||||
// gill, Seite 141
|
||||
|
||||
if (a == 0 || b == 0) return 0;
|
||||
|
||||
a = Math.abs(a);
|
||||
b = Math.abs(b);
|
||||
if (b==1)return a;
|
||||
if (a==1)return b;
|
||||
|
||||
long u = a;
|
||||
long v = b;
|
||||
|
||||
// FIXME - Handle overflow
|
||||
while (a != b) {
|
||||
if (a < b) {
|
||||
b -= a;
|
||||
v += u;
|
||||
} else {
|
||||
a -= b;
|
||||
u += v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//return a; // gcd
|
||||
return (u + v) / 2; // scm
|
||||
}
|
||||
/**
|
||||
* Returns an int whose value is the smallest common multiple of
|
||||
* <tt>abs(a)</tt> and <tt>abs(b)</tt>. Returns 0 if
|
||||
* <tt>a==0 || b==0</tt>.
|
||||
*
|
||||
* @param a value with with the SCM is to be computed.
|
||||
* @param b value with with the SCM is to be computed.
|
||||
* @return <tt>SCM(a, b)</tt>
|
||||
*/
|
||||
public static BigInteger scm(BigInteger a, BigInteger b) {
|
||||
// Quelle:
|
||||
// Herrmann, D. (1992). Algorithmen Arbeitsbuch.
|
||||
// Bonn, München Paris: Addison Wesley.
|
||||
// gill, Seite 141
|
||||
|
||||
if (a.compareTo(BigInteger.ZERO) == 0 || b.compareTo(BigInteger.ZERO) == 0) {
|
||||
return BigInteger.ZERO;
|
||||
}
|
||||
|
||||
a = a.abs();
|
||||
b = b.abs();
|
||||
if (b.compareTo(BigInteger.ONE)==0)return a;
|
||||
if (a.compareTo(BigInteger.ONE)==0)return b;
|
||||
|
||||
BigInteger u = a;
|
||||
BigInteger v = b;
|
||||
|
||||
// FIXME - Handle overflow
|
||||
while (a.compareTo(b) != 0) {
|
||||
if (a .compareTo( b)<0) {
|
||||
b = b.subtract(a);
|
||||
v = v.add(u);
|
||||
} else {
|
||||
a = a.subtract(b);
|
||||
u = u.add(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//return a; // gcd
|
||||
return (u.add(v)).divide(BigInteger.valueOf(2)); // scm
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses all 32 bits of the provided integer value.
|
||||
*/
|
||||
public static int reverseBits(int a) {
|
||||
return reverseBits(a, 32);
|
||||
}
|
||||
/**
|
||||
* Reverses specified number of bits of the provided integer value.
|
||||
* @param a The number.
|
||||
* @param numBits The number of bits (must be between 1 and 32).
|
||||
*/
|
||||
public static int reverseBits(int a, int numBits) {
|
||||
int b = 0;
|
||||
for (int i=0; i < numBits; i++) {
|
||||
b <<= 1;
|
||||
b |= (a & 1);
|
||||
a >>>= 1;
|
||||
}
|
||||
return b;
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i=0; i < 8; i++) {
|
||||
int a = 1<<i;
|
||||
int b = reverseBits(a, 3);
|
||||
System.out.println(a+" - "+b);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,492 @@
|
||||
/*
|
||||
* @(#)Rational.java
|
||||
*
|
||||
* Copyright (c) 2009-2011 Werner Randelshofer, Goldau, Switzerland.
|
||||
* All rights reserved.
|
||||
*
|
||||
* You may not use, copy or modify this file, except in compliance with the
|
||||
* license agreement you entered into with Werner Randelshofer.
|
||||
* For details see accompanying license terms.
|
||||
*/
|
||||
package org.monte.media.math;
|
||||
|
||||
import static java.lang.Math.*;
|
||||
import java.math.BigInteger;
|
||||
import static org.monte.media.math.IntMath.*;
|
||||
|
||||
/**
|
||||
* Represents a TIFF RATIONAL number. <p> Two LONGs 32-bit (4-byte) unsigned
|
||||
* integer: the first represents the numerator of a fraction; the second, the
|
||||
* denominator. </p> <p> Invariants: </p> <ul> <li>denominator>=0, the
|
||||
* denominator is always a positive integer</li> <li>0/1 is the unique
|
||||
* representation of 0.</li> <li>1/0,-1/0 are the unique representations of
|
||||
* infinity.</li> </ul>
|
||||
*
|
||||
* @author Werner Randelshofer
|
||||
* @version $Id: Rational.java 299 2013-01-03 07:40:18Z werner $
|
||||
*/
|
||||
public class Rational extends Number {
|
||||
|
||||
public static final Rational ONE = new Rational(1, 1,false);
|
||||
public static final Rational ZERO = new Rational(0, 1,false);
|
||||
public static final long serialVersionUID = 1L;
|
||||
private final long num;
|
||||
private final long den;
|
||||
|
||||
public Rational(long numerator) {
|
||||
this(numerator, 1);
|
||||
}
|
||||
|
||||
public Rational(long numerator, long denominator) {
|
||||
this(numerator, denominator, true);
|
||||
}
|
||||
|
||||
private Rational(long numerator, long denominator, boolean reduceFraction) {
|
||||
if (numerator == 0) {
|
||||
// Invariant: 0/1 is unique representation of 0
|
||||
denominator = 1;
|
||||
}
|
||||
|
||||
if (denominator == 0) {
|
||||
// Invariant: 1/0, -1/0 are unique representations of infinity
|
||||
numerator = (numerator > 0) ? 1 : -1;
|
||||
} else if (denominator < 0) {
|
||||
// Invariant: denominator is always positive
|
||||
denominator = -denominator;
|
||||
numerator = -numerator;
|
||||
}
|
||||
|
||||
if (reduceFraction) {
|
||||
long g = gcd(numerator, denominator);
|
||||
num = numerator / g;
|
||||
den = denominator / g;
|
||||
} else {
|
||||
num = numerator;
|
||||
den = denominator;
|
||||
}
|
||||
}
|
||||
|
||||
private Rational(BigInteger numerator, BigInteger denominator, boolean reduceFraction) {
|
||||
if (numerator.equals(BigInteger.ZERO)) {
|
||||
// Invariant: 0/1 is unique representation of 0
|
||||
denominator = BigInteger.ONE;
|
||||
}
|
||||
|
||||
if (denominator.equals(BigInteger.ZERO)) {
|
||||
// Invariant: 1/0, -1/0 are unique representations of infinity
|
||||
numerator = (numerator.compareTo(BigInteger.ZERO) > 0) ? BigInteger.ONE : BigInteger.ONE.negate();
|
||||
} else if (denominator.compareTo(BigInteger.ZERO) < 0) {
|
||||
// Invariant: denominator is always positive
|
||||
denominator = denominator.negate();
|
||||
numerator = numerator.negate();
|
||||
}
|
||||
|
||||
BigInteger numB, denB;
|
||||
if (reduceFraction) {
|
||||
BigInteger g = gcd(numerator, denominator);
|
||||
numB = numerator.divide(g);
|
||||
denB = denominator.divide(g);
|
||||
} else {
|
||||
numB = numerator;
|
||||
denB = denominator;
|
||||
}
|
||||
int bitLength = Math.max(numB.bitLength(), denB.bitLength());
|
||||
if (bitLength > 63) {
|
||||
numB = numB.shiftRight(bitLength - 63);
|
||||
denB = denB.shiftRight(bitLength - 63);
|
||||
if (numB.equals(BigInteger.ZERO)) {
|
||||
// Invariant: 0/1 is unique representation of 0
|
||||
denB = BigInteger.ONE;
|
||||
}
|
||||
|
||||
if (denB.equals(BigInteger.ZERO)) {
|
||||
// Invariant: 1/0, -1/0 are unique representations of infinity
|
||||
numB = (numB.compareTo(BigInteger.ZERO) > 0) ? BigInteger.ONE : BigInteger.ONE.negate();
|
||||
|
||||
}
|
||||
}
|
||||
num = numB.longValue();
|
||||
den = denB.longValue();
|
||||
}
|
||||
|
||||
public Rational(Rational r) {
|
||||
this(r.num, r.den);
|
||||
}
|
||||
|
||||
public long getNumerator() {
|
||||
return num;
|
||||
}
|
||||
|
||||
public long getDenominator() {
|
||||
return den;
|
||||
}
|
||||
|
||||
public Rational add(Rational that) {
|
||||
return add(that, true);
|
||||
}
|
||||
|
||||
private Rational add(Rational that, boolean reduceFraction) {
|
||||
if (this.den == that.den) {
|
||||
// => same denominator: add numerators
|
||||
return new Rational(this.num + that.num, this.den, reduceFraction);
|
||||
}
|
||||
|
||||
// FIXME - handle overflow
|
||||
long s = scm(this.den, that.den);
|
||||
Rational result = new Rational(
|
||||
this.num * (s / this.den) + that.num * (s / that.den),
|
||||
s, reduceFraction);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning. Rational is supposed to be immutable. *
|
||||
*
|
||||
* private Rational addAssign(Rational that) { if (this.den == that.den) {
|
||||
* // => same denominator: add numerators this.num += that.num; return this;
|
||||
* }
|
||||
*
|
||||
* // FIXME - handle overflow long s = scm(this.den, that.den); this.num =
|
||||
* this.num * (s / this.den) + that.num * (s / that.den); this.den = s;
|
||||
*
|
||||
*
|
||||
* return reduceAssign(); }
|
||||
*/
|
||||
public Rational subtract(Rational that) {
|
||||
return add(that.negate());
|
||||
}
|
||||
|
||||
public Rational negate() {
|
||||
return valueOf(-num, den);
|
||||
}
|
||||
|
||||
public Rational inverse() {
|
||||
return valueOf(den, num, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the closest rational with the specified denominator which is
|
||||
* smaller or equal than this number.
|
||||
*/
|
||||
public Rational floor(long d) {
|
||||
if (d == den) {
|
||||
return valueOf(num, den);
|
||||
}
|
||||
long s = scm(this.den, d);
|
||||
|
||||
if (s == d) {
|
||||
return valueOf(num * s / den, d);
|
||||
} else if (s == den) {
|
||||
return valueOf(num * d / den, d);
|
||||
} else {
|
||||
return valueOf(num * d / den, d);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the closest rational with the specified denominator which is
|
||||
* greater or equal than this number.
|
||||
*/
|
||||
public Rational ceil(long d) {
|
||||
if (d == den) {
|
||||
return valueOf(num, den);
|
||||
}
|
||||
long s = scm(this.den, d);
|
||||
|
||||
if (s == d) {
|
||||
return valueOf((num * s + den - 1) / den, d);
|
||||
} else if (s == den) {
|
||||
return valueOf((num * d + den - 1) / den, d);
|
||||
} else {
|
||||
return valueOf((num * d + den - 1) / den, d);
|
||||
}
|
||||
}
|
||||
|
||||
public Rational multiply(Rational that) {
|
||||
if (abs(this.num) < Integer.MAX_VALUE
|
||||
&& abs(this.den) < Integer.MAX_VALUE
|
||||
&& abs(that.num) < Integer.MAX_VALUE
|
||||
&& abs(that.den) < Integer.MAX_VALUE) {
|
||||
return valueOf(this.num * that.num,
|
||||
this.den * that.den);
|
||||
} else {
|
||||
return new Rational(
|
||||
BigInteger.valueOf(this.num).multiply(BigInteger.valueOf(that.num)),
|
||||
BigInteger.valueOf(this.den).multiply(BigInteger.valueOf(that.den)),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
public Rational multiply(long integer) {
|
||||
if (integer==0) {
|
||||
return ZERO;
|
||||
} else if (this.den % integer == 0) {
|
||||
return valueOf(
|
||||
this.num,
|
||||
this.den / integer);
|
||||
} else if (abs(this.num) < Integer.MAX_VALUE
|
||||
&& abs(integer) < Integer.MAX_VALUE) {
|
||||
return valueOf(
|
||||
this.num * integer,
|
||||
this.den);
|
||||
} else {
|
||||
return new Rational(
|
||||
BigInteger.valueOf(this.num).multiply(BigInteger.valueOf(integer)),
|
||||
BigInteger.valueOf(this.den), true);
|
||||
}
|
||||
}
|
||||
|
||||
public Rational divide(Rational that) {
|
||||
if (abs(this.num) < Integer.MAX_VALUE
|
||||
&& abs(this.den) < Integer.MAX_VALUE
|
||||
&& abs(that.num) < Integer.MAX_VALUE
|
||||
&& abs(that.den) < Integer.MAX_VALUE) {
|
||||
return valueOf(this.num * that.den,
|
||||
this.den * that.num);
|
||||
} else {
|
||||
return valueOf(
|
||||
BigInteger.valueOf(this.num).multiply(BigInteger.valueOf(that.den)),
|
||||
BigInteger.valueOf(this.den).multiply(BigInteger.valueOf(that.num)),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
//long gcd = IntMath.gcd(num, den);
|
||||
if (num == 0) {
|
||||
return "0";
|
||||
} else if (den == 1) {
|
||||
return Long.toString(num);
|
||||
} else {
|
||||
return num + "/" + den;
|
||||
/*
|
||||
} else {
|
||||
return Float.toString((float) num / den);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
public String toDescriptiveString() {
|
||||
long gcd = IntMath.gcd(num, den);
|
||||
if (gcd == 0 || num == 0) {
|
||||
return num + "/" + den + " = " + 0;
|
||||
} else if (gcd == den) {
|
||||
return num + "/" + den + " = " + Long.toString(num / den);
|
||||
} else {
|
||||
return num + "/" + den + " ≈ " + ((float) num / den);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intValue() {
|
||||
return (int) (num / den);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long longValue() {
|
||||
return num / den;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float floatValue() {
|
||||
return (float) num / (float) den;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double doubleValue() {
|
||||
return (double) num / (double) den;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final Rational that = (Rational) obj;
|
||||
|
||||
return compareTo(that) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* return { -1, 0, +1 } if a < b, a = b, or a > b.
|
||||
*/
|
||||
public int compareTo(Rational that) {
|
||||
// The following code avoids BigInteger allocation if the denominators
|
||||
// are equal
|
||||
if (this.den == that.den) {
|
||||
if (this.num < that.num) {
|
||||
return -1;
|
||||
} else if (this.num > that.num) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Work with longs if overflow can not occur
|
||||
if (abs(this.num) < Integer.MAX_VALUE
|
||||
&& abs(this.den) < Integer.MAX_VALUE
|
||||
&& abs(that.num) < Integer.MAX_VALUE
|
||||
&& abs(that.den) < Integer.MAX_VALUE) {
|
||||
long lhs = this.num * that.den;
|
||||
long rhs = this.den * that.num;
|
||||
if (lhs < rhs) {
|
||||
return -1;
|
||||
} else if (lhs > rhs) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Use big integers to avoid overflows
|
||||
BigInteger lhs;
|
||||
BigInteger rhs;
|
||||
lhs = BigInteger.valueOf(this.num).multiply(BigInteger.valueOf(that.den));
|
||||
rhs = BigInteger.valueOf(this.den).multiply(BigInteger.valueOf(that.num));
|
||||
|
||||
return lhs.compareTo(rhs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) ((num ^ (num >>> 32))
|
||||
^ (den ^ (den >>> 32)));
|
||||
|
||||
}
|
||||
|
||||
public static Rational max(Rational a, Rational b) {
|
||||
return (a.compareTo(b) >= 0) ? a : b;
|
||||
}
|
||||
|
||||
public static Rational min(Rational a, Rational b) {
|
||||
return (a.compareTo(b) <= 0) ? a : b;
|
||||
}
|
||||
|
||||
public boolean isZero() {
|
||||
return num == 0;
|
||||
}
|
||||
|
||||
public boolean isLessOrEqualZero() {
|
||||
return num <= 0;
|
||||
}
|
||||
|
||||
public static Rational valueOf(double d) {
|
||||
if (d == 0) {
|
||||
return valueOf(0, 1);
|
||||
}
|
||||
if (abs(d) > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Value " + d + " is too big.");
|
||||
}
|
||||
if (Double.isInfinite(d)) {
|
||||
return valueOf((long) signum(d), 0);
|
||||
}
|
||||
if (Double.isNaN(d)) {
|
||||
return valueOf(0, 1); // no way to express a NaN :-(
|
||||
}
|
||||
return toRational(d, Integer.MAX_VALUE, 100);
|
||||
}
|
||||
|
||||
public static Rational valueOf(long num, long den) {
|
||||
return valueOf(num, den, true);
|
||||
}
|
||||
|
||||
private static Rational valueOf(long num, long den, boolean reduceFraction) {
|
||||
if (num == den) {
|
||||
return ONE;
|
||||
}
|
||||
if (num == 0) {
|
||||
return ZERO;
|
||||
}
|
||||
return new Rational(num, den, reduceFraction);
|
||||
}
|
||||
|
||||
public static Rational valueOf(BigInteger num, BigInteger den) {
|
||||
return valueOf(num, den, true);
|
||||
}
|
||||
|
||||
private static Rational valueOf(BigInteger num, BigInteger den, boolean reduceFraction) {
|
||||
if (num.equals(den)) {
|
||||
return ONE;
|
||||
}
|
||||
if (num.equals(BigInteger.ZERO)) {
|
||||
return ZERO;
|
||||
}
|
||||
return new Rational(num, den, reduceFraction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iteratively computes rational from double. <p>Reference:<br> <a
|
||||
* href="http://www2.fz-juelich.de/video/cpp/html/exercises/exercise/Rational_cpp.html">
|
||||
* http://www2.fz-juelich.de/video/cpp/html/exercises/exercise/Rational_cpp.html</a>
|
||||
* </p>
|
||||
*/
|
||||
private static Rational toRational(double x, double limit, int iterations) {
|
||||
double intpart = Math.floor(x);
|
||||
double fractpart = x - intpart;
|
||||
double d = 1.0 / fractpart;
|
||||
long left = (long) intpart;
|
||||
if (d > limit || iterations == 0) {
|
||||
return valueOf(left, 1, false);
|
||||
} else {
|
||||
return valueOf(left, 1, false).add(toRational(d, limit * 0.1, iterations - 1).inverse(), false);
|
||||
}
|
||||
}
|
||||
|
||||
public Rational round(long d) {
|
||||
if (d == den) {
|
||||
return valueOf(num, den);
|
||||
}
|
||||
|
||||
Rational fl = floor(d);
|
||||
Rational diffFl = subtract(fl);
|
||||
|
||||
if (diffFl.isZero()) {
|
||||
return fl;
|
||||
}
|
||||
|
||||
Rational cl = ceil(d);
|
||||
Rational diffCl = subtract(cl);
|
||||
if (diffCl.isZero()) {
|
||||
return cl;
|
||||
}
|
||||
|
||||
if (diffFl.isNegative()) {
|
||||
diffFl = diffFl.negate();
|
||||
}
|
||||
if (diffCl.isNegative()) {
|
||||
diffCl = diffCl.negate();
|
||||
}
|
||||
return diffFl.compareTo(diffCl) <= 0 ? fl : cl;
|
||||
}
|
||||
|
||||
private boolean isNegative() {
|
||||
return num < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string.
|
||||
*
|
||||
* A rational can be represented in the following ways: <li>As a long
|
||||
* number</li> <li>As a double number</li> <li>As an integer/integer
|
||||
* rational number</li>
|
||||
*
|
||||
* @throws NumberFormatException if str can not be parsed.
|
||||
*/
|
||||
public static Rational valueOf(String str) {
|
||||
int p = str.indexOf('/');
|
||||
if (p != -1) {
|
||||
return valueOf(Long.valueOf(str.substring(0, p)), Long.valueOf(str.substring(p + 1)));
|
||||
}
|
||||
try {
|
||||
return valueOf(Long.valueOf(str));
|
||||
} catch (NumberFormatException e) {
|
||||
return valueOf(Double.valueOf(str));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user