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};