Math
approximatelyEqual
Checks if two numbers are approximately equal to each other.
Use Math.abs()
to compare the absolute difference of the two values to epsilon
. Omit the third parameter, epsilon
, to use a default value of 0.001
.
检查两个数是否近似相等。
使用 Math.abs()
将两个值的绝对差值与 epsilon
进行比较。 省略第三个参数 epsilon
,使用默认值0.001
。
const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;
approximatelyEqual(Math.PI / 2.0, 1.5708); // true
average
返回两个或更多数字的平均值。
使用 array. prototype.reduce()
将每个值累加,初始值为 0
,然后除以数组的 length
。
const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;
average(...[1, 2, 3]); // 2 average(1, 2, 3); // 2
averageBy
使用提供的函数将每个元素映射到一个值后,返回数组的平均值。
使用 Array.prototype.map()
将每个元素映射到 fn
函数的返回值,使用 array. prototype.reduce()
将每个值累加,初始值为 0
,然后除以数组的 length
。
const averageBy = (arr, fn) => arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) / arr.length;
averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 5 averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 5
binomialCoefficient
Evaluates the binomial coefficient of two integers n
and k
.
Use Number.isNaN()
to check if any of the two values is NaN
. Check if k
is less than 0
, greater than or equal to n
, equal to 1
or n - 1
and return the appropriate result. Check if n - k
is less than k
and switch their values accordingly. Loop from 2
through k
and calculate the binomial coefficient. Use Math.round()
to account for rounding errors in the calculation.
const binomialCoefficient = (n, k) => { if (Number.isNaN(n) || Number.isNaN(k)) return NaN; if (k < 0 || k > n) return 0; if (k === 0 || k === n) return 1; if (k === 1 || k === n - 1) return n; if (n - k < k) k = n - k; let res = n; for (let j = 2; j <= k; j++) res *= (n - j + 1) / j; return Math.round(res); };
binomialCoefficient(8, 2); // 28
clampNumber
Clamps num
within the inclusive range specified by the boundary values a
and b
.
If num
falls within the range, return num
. Otherwise, return the nearest number in the range.
将num夹在由边值a和b指定的包含范围内。
在边界值“a”和“b”指定的包含范围内钳位num
。
返回由边界值 a
和 b
限定范围内的 num
。
如果 num
在限定范围内,则返回 num
。 否则,返回范围内最接近 num
的数字。
const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
clampNumber(2, 3, 5); // 3 clampNumber(1, -1, -5); // -1
degreesToRads
Converts an angle from degrees to radians.
Use Math.PI
and the degree to radian formula to convert the angle from degrees to radians.
const degreesToRads = deg => (deg * Math.PI) / 180.0;
degreesToRads(90.0); // ~1.5708
digitize
Converts a number to an array of digits.
Convert the number to a string, using the spread operator (...
) to build an array. Use Array.prototype.map()
and parseInt()
to transform each value to an integer.
const digitize = n => [...`${n}`].map(i => parseInt(i));
digitize(123); // [1, 2, 3]
distance
Returns the distance between two points.
Use Math.hypot()
to calculate the Euclidean distance between two points.
const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
distance(1, 1, 2, 3); // 2.23606797749979
elo
Computes the new ratings between two or more opponents using the Elo rating system. It takes an array of pre-ratings and returns an array containing post-ratings. The array should be ordered from best performer to worst performer (winner -> loser).
Use the exponent **
operator and math operators to compute the expected score (chance of winning). of each opponent and compute the new rating for each. Loop through the ratings, using each permutation to compute the post-Elo rating for each player in a pairwise fashion. Omit the second argument to use the default kFactor
of 32.
const elo = ([...ratings], kFactor = 32, selfRating) => { const [a, b] = ratings; const expectedScore = (self, opponent) => 1 / (1 + 10 ** ((opponent - self) / 400)); const newRating = (rating, i) => (selfRating || rating) + kFactor * (i - expectedScore(i ? a : b, i ? b : a)); if (ratings.length === 2) return [newRating(a, 1), newRating(b, 0)]; for (let i = 0, len = ratings.length; i < len; i++) { let j = i; while (j < len - 1) { j++; [ratings[i], ratings[j]] = elo([ratings[i], ratings[j]], kFactor); } } return ratings; };
// Standard 1v1s elo([1200, 1200]); // [1216, 1184] elo([1200, 1200], 64); // [1232, 1168] // 4 player FFA, all same rank elo([1200, 1200, 1200, 1200]).map(Math.round); // [1246, 1215, 1185, 1154] /* For teams, each rating can adjusted based on own team's average rating vs. average rating of opposing team, with the score being added to their own individual rating by supplying it as the third argument. */
factorial
Calculates the factorial of a number.
Use recursion. If n
is less than or equal to 1
, return 1
. Otherwise, return the product of n
and the factorial of n - 1
. Throws an exception if n
is a negative number.
const factorial = n => n < 0 ? (() => { throw new TypeError('Negative numbers are not allowed!'); })() : n <= 1 ? 1 : n * factorial(n - 1);
factorial(6); // 720
fibonacci
Generates an array, containing the Fibonacci sequence, up until the nth term.
Create an empty array of the specific length, initializing the first two values (0
and 1
). Use Array.prototype.reduce()
to add values into the array, using the sum of the last two values, except for the first two.
const fibonacci = n => Array.from({ length: n }).reduce( (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), [] );
fibonacci(6); // [0, 1, 1, 2, 3, 5]
gcd
Calculates the greatest common divisor between two or more numbers/arrays.
The inner _gcd
function uses recursion. Base case is when y
equals 0
. In this case, return x
. Otherwise, return the GCD of y
and the remainder of the division x/y
.
const gcd = (...arr) => { const _gcd = (x, y) => (!y ? x : gcd(y, x % y)); return [...arr].reduce((a, b) => _gcd(a, b)); };
gcd(8, 36); // 4 gcd(...[12, 8, 32]); // 4
geometricProgression
Initializes an array containing the numbers in the specified range where start
and end
are inclusive and the ratio between two terms is step
. Returns an error if step
equals 1
.
Use Array.from()
, Math.log()
and Math.floor()
to create an array of the desired length, Array.prototype.map()
to fill with the desired values in a range. Omit the second argument, start
, to use a default value of 1
. Omit the third argument, step
, to use a default value of 2
.
const geometricProgression = (end, start = 1, step = 2) => Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map( (v, i) => start * step ** i );
geometricProgression(256); // [1, 2, 4, 8, 16, 32, 64, 128, 256] geometricProgression(256, 3); // [3, 6, 12, 24, 48, 96, 192] geometricProgression(256, 1, 4); // [1, 4, 16, 64, 256]
hammingDistance
Calculates the Hamming distance between two values.
Use XOR operator (^
) to find the bit difference between the two numbers, convert to a binary string using toString(2)
. Count and return the number of 1
s in the string, using match(/1/g)
.
const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length;
hammingDistance(2, 3); // 1
inRange
Checks if the given number falls within the given range.
Use arithmetic comparison to check if the given number is in the specified range. If the second parameter, end
, is not specified, the range is considered to be from 0
to start
.
const inRange = (n, start, end = null) => { if (end && start > end) [end, start] = [start, end]; return end == null ? n >= 0 && n < start : n >= start && n < end; };
inRange(3, 2, 5); // true inRange(3, 4); // true inRange(2, 3, 5); // false inRange(3, 2); // false
isDivisible
Checks if the first numeric argument is divisible by the second one.
Use the modulo operator (%
) to check if the remainder is equal to 0
.
const isDivisible = (dividend, divisor) => dividend % divisor === 0;
isDivisible(6, 3); // true
isEven
Returns true
if the given number is even, false
otherwise.
Checks whether a number is odd or even using the modulo (%
) operator. Returns true
if the number is even, false
if the number is odd.
const isEven = num => num % 2 === 0;
isEven(3); // false
isNegativeZero
Checks if the given value is equal to negative zero (-0
).
Checks whether a passed value is equal to 0
and if 1
divided by the value equals -Infinity
.
const isNegativeZero = val => val === 0 && 1 / val === -Infinity;
isNegativeZero(-0); // true isNegativeZero(0); // false
isPrime
Checks if the provided integer is a prime number.
Check numbers from 2
to the square root of the given number. Return false
if any of them divides the given number, else return true
, unless the number is less than 2
.
const isPrime = num => { const boundary = Math.floor(Math.sqrt(num)); for (var i = 2; i <= boundary; i++) if (num % i === 0) return false; return num >= 2; };
isPrime(11); // true
lcm
Returns the least common multiple of two or more numbers.
Use the greatest common divisor (GCD) formula and the fact that lcm(x,y) = x * y / gcd(x,y)
to determine the least common multiple. The GCD formula uses recursion.
const lcm = (...arr) => { const gcd = (x, y) => (!y ? x : gcd(y, x % y)); const _lcm = (x, y) => (x * y) / gcd(x, y); return [...arr].reduce((a, b) => _lcm(a, b)); };
lcm(12, 7); // 84 lcm(...[1, 3, 4, 5]); // 60
luhnCheck
Implementation of the Luhn Algorithm used to validate a variety of identification numbers, such as credit card numbers, IMEI numbers, National Provider Identifier numbers etc.
Use String.prototype.split('')
, Array.prototype.reverse()
and Array.prototype.map()
in combination with parseInt()
to obtain an array of digits. Use Array.prototype.splice(0,1)
to obtain the last digit. Use Array.prototype.reduce()
to implement the Luhn Algorithm. Return true
if sum
is divisible by 10
, false
otherwise.
const luhnCheck = num => { let arr = (num + '') .split('') .reverse() .map(x => parseInt(x)); let lastDigit = arr.splice(0, 1)[0]; let sum = arr.reduce((acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), 0); sum += lastDigit; return sum % 10 === 0; };
luhnCheck('4485275742308327'); // true luhnCheck(6011329933655299); // false luhnCheck(123456789); // false
mapNumRange
Maps a number from one range to another range.
Returns num
mapped between outMin
-outMax
from inMin
-inMax
.
const mapNumRange = (num, inMin, inMax, outMin, outMax) => ((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
mapNumRange(5, 0, 10, 0, 100); // 50
Recommended Resource - JavaScript: From Fundamentals to Functional JS
Learn higher-order functions, closures, scope, master key functional methods like map, reduce and filter and promises and ES6+ asynchronous JavaScript.
maxBy
Returns the maximum value of an array, after mapping each element to a value using the provided function.
Use Array.prototype.map()
to map each element to the value returned by fn
, Math.max()
to get the maximum value.
const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
maxBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 8 maxBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 8
median
Returns the median of an array of numbers.
Find the middle of the array, use Array.prototype.sort()
to sort the values. Return the number at the midpoint if length
is odd, otherwise the average of the two middle numbers.
const median = arr => { const mid = Math.floor(arr.length / 2), nums = [...arr].sort((a, b) => a - b); return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2; };
median([5, 6, 50, 1, -5]); // 5
midpoint
Calculates the midpoint between two pairs of (x,y) points.
Destructure the array to get x1
, y1
, x2
and y2
, calculate the midpoint for each dimension by dividing the sum of the two endpoints by 2
.
const midpoint = ([x1, y1], [x2, y2]) => [(x1 + x2) / 2, (y1 + y2) / 2];
midpoint([2, 2], [4, 4]); // [3, 3] midpoint([4, 4], [6, 6]); // [5, 5] midpoint([1, 3], [2, 4]); // [1.5, 3.5]
minBy
Returns the minimum value of an array, after mapping each element to a value using the provided function.
Use Array.prototype.map()
to map each element to the value returned by fn
, Math.min()
to get the minimum value.
const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
minBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 2 minBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 2
percentile
Uses the percentile formula to calculate how many numbers in the given array are less or equal to the given value.
Use Array.prototype.reduce()
to calculate how many numbers are below the value and how many are the same value and apply the percentile formula.
const percentile = (arr, val) => (100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length;
percentile([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 6); // 55
powerset
Returns the powerset of a given array of numbers.
Use Array.prototype.reduce()
combined with Array.prototype.map()
to iterate over elements and combine into an array containing all combinations.
const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
powerset([1, 2]); // [[], [1], [2], [2, 1]]
primes
Generates primes up to a given number, using the Sieve of Eratosthenes.
Generate an array from 2
to the given number. Use Array.prototype.filter()
to filter out the values divisible by any number from 2
to the square root of the provided number.
const primes = num => { let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2), sqroot = Math.floor(Math.sqrt(num)), numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2); numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x))); return arr; };
primes(10); // [2,3,5,7]
radsToDegrees
Converts an angle from radians to degrees.
Use Math.PI
and the radian to degree formula to convert the angle from radians to degrees.
const radsToDegrees = rad => (rad * 180.0) / Math.PI;
radsToDegrees(Math.PI / 2); // 90
randomIntArrayInRange
Returns an array of n random integers in the specified range.
Use Array.from()
to create an empty array of the specific length, Math.random()
to generate a random number and map it to the desired range, using Math.floor()
to make it an integer.
const randomIntArrayInRange = (min, max, n = 1) => Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min);
randomIntArrayInRange(12, 35, 10); // [ 34, 14, 27, 17, 30, 27, 20, 26, 21, 14 ]
randomIntegerInRange
Returns a random integer in the specified range.
Use Math.random()
to generate a random number and map it to the desired range, using Math.floor()
to make it an integer.
const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
randomIntegerInRange(0, 5); // 2
randomNumberInRange
Returns a random number in the specified range.
Use Math.random()
to generate a random value, map it to the desired range using multiplication.
const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
randomNumberInRange(2, 10); // 6.0211363285087005
round
Rounds a number to a specified amount of digits.
Use Math.round()
and template literals to round the number to the specified number of digits. Omit the second argument, decimals
to round to an integer.
const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
round(1.005, 2); // 1.01
sdbm
Hashes the input string into a whole number.
Use String.prototype.split('')
and Array.prototype.reduce()
to create a hash of the input string, utilizing bit shifting.
const sdbm = str => { let arr = str.split(''); return arr.reduce( (hashCode, currentVal) => (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode), 0 ); };
sdbm('name'); // -3521204949
standardDeviation
Returns the standard deviation of an array of numbers.
Use Array.prototype.reduce()
to calculate the mean, variance and the sum of the variance of the values, the variance of the values, then determine the standard deviation. You can omit the second argument to get the sample standard deviation or set it to true
to get the population standard deviation.
const standardDeviation = (arr, usePopulation = false) => { const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; return Math.sqrt( arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) / (arr.length - (usePopulation ? 0 : 1)) ); };
standardDeviation([10, 2, 38, 23, 38, 23, 21]); // 13.284434142114991 (sample) standardDeviation([10, 2, 38, 23, 38, 23, 21], true); // 12.29899614287479 (population)
sum
Returns the sum of two or more numbers/arrays.
Use Array.prototype.reduce()
to add each value to an accumulator, initialized with a value of 0
.
const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);
sum(1, 2, 3, 4); // 10 sum(...[1, 2, 3, 4]); // 10
sumBy
Returns the sum of an array, after mapping each element to a value using the provided function.
Use Array.prototype.map()
to map each element to the value returned by fn
, Array.prototype.reduce()
to add each value to an accumulator, initialized with a value of 0
.
const sumBy = (arr, fn) => arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0);
sumBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 20 sumBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 20
sumPower
Returns the sum of the powers of all the numbers from start
to end
(both inclusive).
Use Array.prototype.fill()
to create an array of all the numbers in the target range, Array.prototype.map()
and the exponent operator (**
) to raise them to power
and Array.prototype.reduce()
to add them together. Omit the second argument, power
, to use a default power of 2
. Omit the third argument, start
, to use a default starting value of 1
.
const sumPower = (end, power = 2, start = 1) => Array(end + 1 - start) .fill(0) .map((x, i) => (i + start) ** power) .reduce((a, b) => a + b, 0);
sumPower(10); // 385 sumPower(10, 3); // 3025 sumPower(10, 3, 5); // 2925
toSafeInteger
Converts a value to a safe integer.
Use Math.max()
and Math.min()
to find the closest safe value. Use Math.round()
to convert to an integer.
const toSafeInteger = num => Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER));
toSafeInteger('3.2'); // 3 toSafeInteger(Infinity); // 9007199254740991
vectorDistance
Returns the distance between two vectors.
Use Array.prototype.reduce()
, Math.pow()
and Math.sqrt()
to calculate the Euclidean distance between two vectors.
const vectorDistance = (...coords) => { let pointLength = Math.trunc(coords.length / 2); let sum = coords .slice(0, pointLength) .reduce((acc, val, i) => acc + Math.pow(val - coords[pointLength + i], 2), 0); return Math.sqrt(sum); };
vectorDistance(10, 0, 5, 20, 0, 10); // 11.180339887498949