-
Notifications
You must be signed in to change notification settings - Fork 8
/
Fraction.java
187 lines (164 loc) · 7.08 KB
/
Fraction.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import java.math.BigInteger;
/**
* The class Fraction implements the integer fractions and some
* of their arithmetic and comparison operations. The fractions
* are internally implemented using Java's BigInteger class for
* arbitrarily large integer values.
* @author Ilkka Kokkarinen
*/
public class Fraction implements Comparable<Fraction> {
// A fraction is internally encoded as numerator and denominator, both BigIntegers.
private BigInteger num; // the numerator
private BigInteger den; // the denominator, should always be > 0
// The getter methods. Note that we don't have setter methods, since the Fraction
// class is immutable, which means that an object, once created, cannot change its
// state. (Immutability has various advantages that aren't intuitive quite yet.)
/**
* Return the numerator of this fraction.
* @return The numerator of this fraction.
*/
public BigInteger getNum() { return num; }
/**
* Return the denominator of this fraction.
* @return The denominator of this fraction.
*/
public BigInteger getDen() { return den; }
/**
* Construct a fraction from given numerator and denominator, as ints.
* @param num The numerator of the fraction.
* @param den The denominator of the fraction.
*/
public Fraction(int num, int den) {
this(new BigInteger("" + num), new BigInteger("" + den));
}
/**
* Construct a fraction from given numerator and denominator, as BigIntegers.
* @param num The numerator of the fraction.
* @param den The denominator of the fraction.
*/
public Fraction(BigInteger num, BigInteger den) {
this.num = num;
this.den = den;
simplify();
}
/**
* Construct a fraction that is an integer, from an int.
* @param num The integer part of this fraction.
*/
public Fraction(int num) {
this(new BigInteger("" + num));
}
/**
* Construct a fraction that is an integer, from a BigInteger.
* @param num The integer part of this fraction.
*/
public Fraction(BigInteger num) {
this.num = num;
this.den = BigInteger.ONE;
// no need to simplify, fraction is already in lowest terms
}
// Addition of fractions. Note that to add two fractions, call this method for one of them,
// and pass the second one as parameter. This method doesn't modify either fraction, but
// creates and returns a new fraction that contains the result.
/**
* Create a new fraction that is the sum of this fraction and the {@code other} fraction.
* @param other The other fraction to add.
* @return A fraction that contains the sum of the two fractions.
*/
public Fraction add(Fraction other) {
return new Fraction(this.num.multiply(other.den).add(this.den.multiply(other.num)), this.den.multiply(other.den));
}
/**
* Create a new fraction that is the product of this fraction and the {@code other} fraction.
* @param other The other fraction to multiply.
* @return A fraction that contains the product of the two fractions.
*/
public Fraction multiply(Fraction other) {
return new Fraction(this.num.multiply(other.num), this.den.multiply(other.den));
}
/**
* Create a new fraction that is the difference of this fraction and the {@code other} fraction.
* @param other The other fraction to subtract.
* @return A fraction that contains the difference of the two fractions.
*/
public Fraction subtract(Fraction other) {
return new Fraction(this.num.multiply(other.den).subtract(this.den.multiply(other.num)), this.den.multiply(other.den));
}
/**
* Create a new fraction that is the quotient of this fraction and the {@code other} fraction.
* @param other The other fraction to divide.
* @return A fraction that contains the quotient of the two fractions.
*/
public Fraction divide(Fraction other) {
return new Fraction(this.num.multiply(other.den), this.den.multiply(other.num));
}
/**
* Check the equality of this fraction and the {@code other} fraction.
* @param o The other fraction of the equality comparison.
* @return {@code true} if the fractions are equal, {@code false} otherwise.
*/
@Override public boolean equals(Object o) {
if(o instanceof Fraction) {
// downcast to correct subtype
Fraction other = (Fraction)o;
return (this.num.equals(other.num) && this.den.equals(other.den));
}
else {
return false;
}
}
/**
* Compute the hash code for this object. We combine the hash code from
* the hash codes of the numerator and denominator. The bytes of the
* denominator's hash code are swapped before combining results with
* "exclusive or" operator ^, which you note does not mean the power
* function in Java. Java does not have an integer power function at all.
* Python's power function is **, with ^ in the same "xor" role as here.
* @return The hash code of this Fraction.
*/
@Override public int hashCode() {
int hd = den.hashCode();
int hn = num.hashCode();
// As not to hash a/b and b/a to the same value, do some bitwise
// arithmetic to one of their hash codes to break the symmetry.
hd = (hd >> 16) ^ ~(hd << 16);
// Hash codes are best combined from pieces with bitwise xor.
return hn ^ hd; // ^ is bitwise xor, not exponentiation.
}
/**
* The ordering comparison of fractions.
* @param other The other fraction of the order comparison.
* @return -1, 0 or +1 depending on the result of the comparison.
*/
@Override public int compareTo(Fraction other) {
// We just subtract the fractions and return the sign of result.
Fraction diff = this.subtract(other);
return diff.getNum().signum();
}
/**
* Construct the {@code String} representation of this fraction.
*/
public String toString() {
if(den.equals(BigInteger.ONE)) { return num.toString(); }
else { return num + "/" + den; }
}
// A private method for simplifying the initial value to the lowest terms.
private void simplify() {
if(den.signum() == -1) { // we want the denominator to always be positive
den = den.negate(); num = num.negate();
}
BigInteger gcd = num.gcd(den); // handy!
num = num.divide(gcd); // to simplify a fraction num/den, divide both num
den = den.divide(gcd); // and den by their greatest common divisor
}
// For demonstration purposes.
public static void main(String[] args) {
Fraction a = new Fraction(3, 7); // 3/7
Fraction b = new Fraction(-2, 18); // -1/9
Fraction c = a.add(b); // c = a + b
c = c.multiply(a.subtract(b)); // c = c * (a-b)
System.out.println("a is now " + a);
System.out.println("b is now " + b);
System.out.println("c is now " + c);
}
}