combinations.js (1237B)
1 import { isInteger } from '../../utils/number.js'; 2 import { product } from '../../utils/product.js'; 3 export function combinationsNumber(n, k) { 4 if (!isInteger(n) || n < 0) { 5 throw new TypeError('Positive integer value expected in function combinations'); 6 } 7 8 if (!isInteger(k) || k < 0) { 9 throw new TypeError('Positive integer value expected in function combinations'); 10 } 11 12 if (k > n) { 13 throw new TypeError('k must be less than or equal to n'); 14 } 15 16 var nMinusk = n - k; 17 var answer = 1; 18 var firstnumerator = k < nMinusk ? nMinusk + 1 : k + 1; 19 var nextdivisor = 2; 20 var lastdivisor = k < nMinusk ? k : nMinusk; // balance multiplications and divisions to try to keep intermediate values 21 // in exact-integer range as long as possible 22 23 for (var nextnumerator = firstnumerator; nextnumerator <= n; ++nextnumerator) { 24 answer *= nextnumerator; 25 26 while (nextdivisor <= lastdivisor && answer % nextdivisor === 0) { 27 answer /= nextdivisor; 28 ++nextdivisor; 29 } 30 } // for big n, k, floating point may have caused weirdness in remainder 31 32 33 if (nextdivisor <= lastdivisor) { 34 answer /= product(nextdivisor, lastdivisor); 35 } 36 37 return answer; 38 } 39 combinationsNumber.signature = 'number, number';