This repository has been archived by the owner on May 14, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
approx_fraction.mjs
62 lines (48 loc) · 1.8 KB
/
approx_fraction.mjs
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
// From http://www.mindspring.com/~alanh/fracs.html
// Approximate decimal number `d` into the returned fraction `frac`,
// so that |frac - d| < (10^-precision / 2).
// In other words, return an approximate fraction correct up to the
// `precision`th decimal place.
export default function approximateFraction(d, precision) {
var numerators = [0, 1];
var denominators = [1, 0];
var maxNumerator = getMaxNumerator(d);
var d2 = d;
var calcD,
prevCalcD = NaN;
var acceptableError = Math.pow(10, -precision) / 2;
for (var i = 2; i < 1000; i++) {
var L2 = Math.floor(d2);
numerators[i] = L2 * numerators[i - 1] + numerators[i - 2];
if (Math.abs(numerators[i]) > maxNumerator) return;
denominators[i] = L2 * denominators[i - 1] + denominators[i - 2];
calcD = numerators[i] / denominators[i];
if (Math.abs(calcD - d) < acceptableError || calcD == prevCalcD) {
return numerators[i].toString() + "/" + denominators[i].toString();
}
d2 = 1 / (d2 - L2);
}
}
function getMaxNumerator(f) {
var f2 = null;
var ixe = f.toString().indexOf("E");
if (ixe == -1) ixe = f.toString().indexOf("e");
if (ixe == -1) f2 = f.toString();
else f2 = f.toString().substring(0, ixe);
var digits = null;
var ix = f2.toString().indexOf(".");
if (ix == -1) digits = f2;
else if (ix === 0) digits = f2.substring(1, f2.length);
else if (ix < f2.length)
digits = f2.substring(0, ix) + f2.substring(ix + 1, f2.length);
var L = digits;
var numDigits = L.toString().length;
var L2 = f;
var numIntDigits = L2.toString().length;
if (L2 === 0) numIntDigits = 0;
var numDigitsPastDecimal = numDigits - numIntDigits;
var i;
for (i = numDigitsPastDecimal; i > 0 && L % 2 === 0; i--) L /= 2;
for (i = numDigitsPastDecimal; i > 0 && L % 5 === 0; i--) L /= 5;
return L;
}