(a, b, base = 10, exp = [], d = {}, dlen = 0)
| 21 | * @returns {array} |
| 22 | */ |
| 23 | export function decExp(a, b, base = 10, exp = [], d = {}, dlen = 0) { |
| 24 | if (base < 2 || base > 10) { |
| 25 | throw new RangeError('Unsupported base. Must be in range [2, 10]') |
| 26 | } |
| 27 | |
| 28 | if (a === 0) { |
| 29 | return [0, [], undefined] |
| 30 | } |
| 31 | |
| 32 | if (a === b && dlen === 0) { |
| 33 | return [1, [], undefined] |
| 34 | } |
| 35 | |
| 36 | // d contains the dividends used so far and the corresponding index of its |
| 37 | // euclidean division by b in the expansion array. |
| 38 | d[a] = dlen++ |
| 39 | |
| 40 | if (a < b) { |
| 41 | exp.push(0) |
| 42 | return decExp(a * base, b, base, exp, d, dlen) |
| 43 | } |
| 44 | |
| 45 | // Euclid's division lemma : a = bq + r |
| 46 | const r = a % b |
| 47 | const q = (a - r) / b |
| 48 | |
| 49 | // Decimal expansion (1st element is the integer part) |
| 50 | exp.push(+q.toString(base)) |
| 51 | |
| 52 | if (r === 0) { |
| 53 | // got a regular number (division terminates) |
| 54 | return [exp[0], exp.slice(1), undefined] |
| 55 | } |
| 56 | |
| 57 | // For the next iteration |
| 58 | a = r * base |
| 59 | |
| 60 | // Check if `a` has already been used as a dividend, in which case it means |
| 61 | // the expansion is periodic. |
| 62 | if (a in d) { |
| 63 | return [exp[0], exp.slice(1), d[a] - 1] |
| 64 | } |
| 65 | |
| 66 | return decExp(a, b, base, exp, d, dlen) |
| 67 | } |
no test coverage detected