math.js

View source code here on GitHub!

math.factorial(n)

Compute the factorial of a given number. Note that, unlike the version of this in other languages, this does not guard against imprecision or overflow.

Arguments:
  • n (number)

Returns:

number --

math.nChooseR(n, r)

Returns the number of ways to return r elements from a group of size n. This method guards against imprecision by having a "slow path" for larger values of n.

Arguments:
  • n (number)

  • r (number)

Returns:

number --

 1/**
 2 * Compute the factorial of a given number. Note that, unlike the version of this in other languages, this does not
 3 * guard against imprecision or overflow.
 4 * @param {number} n
 5 * @return {number}
 6 */
 7exports.factorial = function factorial(n) {
 8    let answer = 1;
 9    for (let x = 2; x <= n; x += 1) {
10        answer *= x;
11    }
12    return answer;
13};
14/**
15 * Returns the number of ways to return r elements from a group of size n. This method guards against imprecision by
16 * having a "slow path" for larger values of n.
17 * @param {number} n
18 * @param {number} r
19 * @return {number}
20 */
21exports.nChooseR = function nChooseR(n, r) {
22    if (n <= 20) {
23        return factorial(n) / factorial(r) / factorial(n - r);
24    }
25
26    let answer; let tmp; let i; let j;
27    const factors = new Int8Array(n + 1);
28    // collect factors of final number
29    for (i = 2; i <= n; i += 1) {
30        factors[i] = 1;
31    }
32
33    // negative factor values indicate need to divide
34    for (i = 2; i <= r; i += 1) {
35        factors[i] -= 1;
36    }
37    for (i = 2; i <= n - r; i += 1) {
38        factors[i] -= 1;
39    }
40
41    // this loop reduces to prime factors only
42    for (i = n; i > 1; i -= 1) {
43        for (j = 2; j < i; j += 1) {
44            if (i % j == 0) {
45                factors[j] += factors[i];
46                factors[i / j] += factors[i];
47                factors[i] = 0;
48                break;
49            }
50        }
51    }
52
53    i = j = 2;
54    answer = 1;
55    while (i <= n) {
56        while (factors[i] > 0) {
57            tmp = answer;
58            answer *= i;
59            while (answer < tmp && j <= n) {
60                while (factors[j] < 0) {
61                    tmp /= j;
62                    factors[j] += 1;
63                }
64                j += 1;
65                answer = tmp * i;
66            }
67            if (answer < tmp) {
68                return ulong.MaxValue;
69            } // this indicates an overflow
70            factors[i] -= 1;
71        }
72        i += 1;
73    }
74
75    while (j <= n) {
76        while (factors[j] < 0) {
77            answer /= j;
78            factors[j] += 1;
79        }
80        j += 1;
81    }
82
83    return answer;
84};