-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrational.js
108 lines (87 loc) · 2.59 KB
/
rational.js
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
// @flow
'use strict';
/* ::
import { type Field } from './field';
*/
/* global BigInteger */
// eslint-disable-next-line no-unused-vars
class BigRational /* :: implements Field<BigRational> */ {
/* ::
_n: BigInteger;
_d: BigInteger;
static Zero: BigRational;
static One: BigRational;
*/
constructor(n /* : BigInteger */, d /* :: ?: BigInteger */) {
let realN = n;
let realD = d === undefined ? BigInteger.ONE : d;
if (realD.signum() === 0) {
throw new Error('division by zero');
}
if (realN.signum() === 0) {
this._n = realN;
this._d = BigInteger.ONE;
return;
}
if (realD.signum() < 0) {
realN = realN.negate();
realD = realD.negate();
}
const gcd = realN.gcd(realD);
this._n = realN.divide(gcd);
this._d = realD.divide(gcd);
}
numerator() /* : BigInteger */ {
return this._n;
}
denominator() /* : BigInteger */ {
return this._d;
}
toString(radix /* : ?number */) /* : string */ {
if (this._d.compareTo(BigInteger.ONE) === 0) {
return this._n.toString(radix);
}
return `${this._n.toString(radix)}/${this._d.toString(radix)}`;
}
plus(b /* : BigRational */) /* : BigRational */ {
const gcd = this._d.gcd(b._d);
const a1 = this._n.multiply(b._d.divide(gcd));
const a2 = b._n.multiply(this._d.divide(gcd));
return new BigRational(a1.add(a2), this._d.multiply(b._d).divide(gcd));
}
minus(b /* : BigRational */) /* : BigRational */ {
const gcd = this._d.gcd(b._d);
const a1 = this._n.multiply(b._d.divide(gcd));
const a2 = b._n.multiply(this._d.divide(gcd));
return new BigRational(a1.subtract(a2), this._d.multiply(b._d).divide(gcd));
}
times(b /* : BigRational */) /* : BigRational */ {
const n = this._n.multiply(b._n);
const d = this._d.multiply(b._d);
const gcd = n.gcd(d);
return new BigRational(n.divide(gcd), d.divide(gcd));
}
dividedBy(b /* : BigRational */) /* : BigRational */ {
if (b._n.signum() === 0) {
throw new Error('division by zero');
}
const n = this._n.multiply(b._d);
const d = this._d.multiply(b._n);
const gcd = n.gcd(d);
return new BigRational(n.divide(gcd), d.divide(gcd));
}
equals(b /* : BigRational */) /* : boolean */ {
return this._n.compareTo(b._n) === 0 && this._d.compareTo(b._d) === 0;
}
zero() /* : BigRational */ {
return this.constructor.Zero;
}
one() /* : BigRational */ {
return this.constructor.One;
}
}
BigRational.Zero = new BigRational(BigInteger.ZERO);
BigRational.One = new BigRational(BigInteger.ONE);
/* ::
export { BigRational };
*/