'use strict';
(function(){
var math = {};
math.orig = {};
Object.getOwnPropertyNames(Math).forEach((key) => {
if(typeof Math[key] == "function"){
math.orig[key] = Math[key].bind({});
} else {
math.orig[key] = Math[key];
}
});
Helpers
To start, let’s build out some simple functions which will be important building blocks for our later functions.
isArray
Determines if a given object is an array.
math.isArray = function(obj){
if(Array.isArray) return Array.isArray(obj);
return obj.constructor === Array;
};
isObject
Determines if a given object is an object.
math.isObject = function(obj){
return obj === Object(obj);
};
pluck
Given a non-array, obj
, returns obj
.
Given an array of numbers, returns the array of numbers.
Given an array of objects and a string, ‘key’, returns an array of whatever
was mapped to key
in each object of the array.
math.pluck = function(obj, key){
var arr = obj;
if(math.isArray(obj)){
if(math.isObject(obj[0])){
key = key || 'value';
return arr.map(i => i[key]);
}
return arr.slice();
}
return arr;
};
range
Given a number, s
, range returns an array of integers between 1 and s
(inclusive).
Given two numbers, s
and t
, range returns an array of integers between
t
and s
(inclusive).
Given three numders s
, t
, and i
, range returns an array of integers
between t
and s + i - 1
(inclusive) such that the difference between
each element in the output array is exactly i
.
math.range = function(stop, start, step){
start = start || 1;
step = step || 1;
var length = math.max(math.ceil((stop - start) / step), 0),
range = Array(length);
for (var idx = 0; idx < length; idx++, start += step){
range[idx] = start;
}
return range;
};
repeat
Given an array, obj
, and a number, times
, returns an array which
repeats obj
times
times.
math.repeat([1,2,3], 2)
⇒ [1, 2, 3, 1, 2, 3]
math.repeat = function(obj, times){
if(!math.isArray(obj)){ obj = [obj]; }
if(!times){ return obj; }
var out = [];
for(var i = 0; i < times; i++){
out = out.concat(obj);
}
return out;
};
repeatEach
Given an array, obj
, and a number, each
, returns an array which
repeats each value of obj
each
times.
math.repeatEach([1,2,3], 2)
⇒ [1, 1, 2, 2, 3, 3]
math.repeatEach = function(obj, each){
if(!math.isArray(obj)){ obj = [obj]; }
each = each || 1;
var out = Array(each * obj.length);
obj.forEach(function(el, i){
for(var j = 0; j < each; j++){
out[i * each + j] = el;
}
});
return out;
};
Identifiers
This is a special class of mappers which return boolean variables, identifying if a given number meets a defined criterion. They are distinguished by the naming scheme is[Type] where [Type] is some term that’s meaningful to either Mathematics or Javascript.
isUndefined
Determines if a given object is undefined.
math.isUndefined = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isUndefined);
}
return typeof obj === 'undefined';
};
isNumber
Determines if a given object is a number
math.isNumber = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isNumber);
}
return typeof obj === 'number';
};
isNaN
Determines if a given object is Not a Number
math.isNaN = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isNaN);
}
return math.isNumber(obj) && obj !== +obj;
};
isInteger
Determines if a given object is an integer
math.isInteger = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isInteger);
}
return Number.isInteger(obj);
};
isPositive
Determines whether a number is positive
math.isPositive = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isPositive);
}
return obj > 0;
};
isNegative
Determines whether a number is negative
math.isNegative = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isNegative);
}
return obj < 0;
};
isNonNegative
Determines whether a number is nonnegative
math.isNonNegative = math.isNonnegative = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isNonnegative);
}
return obj >= 0;
};
isNonpositive
Determines whether a number is nonpositive
math.isNonPositive = math.isNonpositive = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isNonpositive);
}
return obj <= 0;
};
isZero
Determines whether a number is Zero
math.isZero = math.iszero = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isZero);
}
return obj === 0;
};
isNonzero
Determines whether a number is nonzero
math.isNonZero = math.isNonzero = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isNonzero);
}
return obj !== 0;
};
isSameSign
Compares the signs of two values
math.isSameSign = function(obj, b){
if(math.isArray(obj)){
return obj.map(i => math.isSameSign(i, b));
}
return (obj >= 0) !== (b < 0);
};
isFinite
Determines whether a number is finite
math.isFinite = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isFinite);
}
return Number.isFinite(obj);
};
isInfinite
Determines whether a number is positive
math.isInfinite = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isInfinite);
}
return !math.isFinite(obj);
};
isEven
Determines whether a number is even.
math.isEven = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isEven);
}
return obj % 2 === 0;
};
isOdd
Determines whether a number is odd.
math.isOdd = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isOdd);
}
return obj % 2 === 1;
};
isPrime
Determines whether a number is prime.
Note that for a numeric input, n, this is O(sqrt(n)). For arrays of size m, it’s O(m*sqrt(n)). It isn’t the most efficient possible implementation, but it’s reasonably simple.
math.isPrime = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isPrime);
}
if(!obj){
return false;
} else if(obj !== 2){
var safeN = math.abs(math.round(obj));
var goUntil = math.ceil(math.sqrt(safeN));
for (var i = 2; i <= goUntil; i++){
if(safeN % i === 0){
return false;
}
}
}
return true;
};
isComposite
Determines whether a number is composite.
math.isComposite = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isComposite);
}
return !math.isPrime(obj);
};
isPowerOfTwo
Determines whether a number is a power of two.
math.isPowerOfTwo = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isPowerOfTwo);
}
return obj && (obj & (obj - 1)) === 0;
};
isPerfect
Determines whether a number is perfect.
Because there are so few which can be represented as integers, it’s vastly more efficient to just store them all than attempt to compute and sum factors or check for Eulerian forms.
math.perfects = [6, 28, 496, 8128, 33550336, 8589869056, 137438691328];
math.isPerfect = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isPerfect);
}
return obj in math.perfects;
};
/#### isValidBinary Determines whether a number is a valid binary number.
math.isValidBinary = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.isValidBinary);
}
var bits = ['0', '1'];
var n = obj + '';
for(var i = 0; i < n.length; i++){
if(!bits.includes(n[i])) return false;
}
return true;
};
Randomizers
Randomizers provide sources of pseudo-randomly values. These are largely based on Math.random, which is not cryptographically secure. Accordingly, these should not be used for applications which require secure random values.
random
Returns a random value between 0 and 1.
Given a number, n
, returns an array of n
random values between 0 and 1.
math.random = function(n){
if(!n) return math.orig.random();
var out = Array(n);
for(var i = 0; i < n; i++){
out[i] = math.random();
}
return out;
};
randomBoolean
Returns a random boolean value.
Given a number, n
, returns an array of n
random booleans.
math.randomBoolean = function(n){
if(!n) return math.orig.random() > 0.5 ? 1 : -1;
var out = Array(n);
for(var i = 0; i < n; i++){
out[i] = math.randomBoolean();
}
return out;
};
randomDirection
AKA randomSign
Returns a random direction (i.e. 1 or -1)
Given a number, n
, returns an array of n
random directions.
math.randomDirection = math.randomSign = function(n){
if(!n) return math.orig.random() > 0.5 ? 1 : -1;
var out = Array(n);
for(var i = 0; i < n; i++){
out[i] = math.randomDirection();
}
return out;
};
randomElement
AKA randomItem
Given an array, return one element selected at random.
math.randomElement = math.randomItem = function(obj, key){
if(key) return math.randomElement(math.pluck(obj, key));
return obj[math.floor(math.random() * obj.length)];
};
randomSample
Given an array, obj
, and a number, m
, returns m
randomly-selected
elements of obj
.
math.randomSample = math.randomsample = function(obj, m){
if(!m || m > obj.length) return obj;
return math.shuffle(obj).slice(0, m);
};
shuffle
Given an array, obj
, returns an array which contains every element of
obj
, but in a random order.
math.shuffle = function(obj, key){
var arr = math.pluck(obj, key),
m = arr.length, t, i;
while (m){
i = math.floor(math.random() * m--);
t = arr[m];
arr[m] = arr[i];
arr[i] = t;
}
return arr;
};
Mappers
Mapper functions accept a single argument (which may be an array of numbers
or objects), and return an object of roughly similar type and size.
For example, passing a number to a mapper should result in a number.
Passing an array of n
numbers should (in most cases) return an array of
n
numbers.
Note that these will also generally work with arrays of objects, provided you pass a ‘key’ argument indicating the key in the object which you wish to operate on.
sign
Returns one of -1, 0, or 1, indicating whether the given obj is negative, zero, or positive
math.sign = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.sign);
}
return math.orig.sign(obj);
};
floor
Returns the greatest integer less than a given value.
math.floor = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.floor);
}
return math.orig.floor(obj);
};
ceil
Returns the least integer greater than a given value.
math.ceil = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.ceil);
}
return math.orig.ceil(obj);
};
round
Returns the nearest integer to a given value.
math.round = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.round);
}
return math.orig.round(obj);
};
toPrecision
Returns a number rounded to the specified precision (a la PHP)
math.toPrecision = math.roundToPrecision = function(obj, precision){
if(math.isArray(obj)){
return obj.map(math.toPrecision);
}
var factor = math.pow(10, precision);
return math.round(obj * factor) / factor;
};
clamp
Returns the nearest value to a number within the range [lower, upper].
math.clamp = function(obj, lower, upper){
if(math.isArray(obj)){
return obj.map(i => math.clamp(i, lower, upper));
}
if(obj < lower){ return lower; }
if(obj > upper){ return upper; }
return obj;
};
trunc
Returns an integer with all digits less than one truncated.
math.trunc = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.trunc);
}
return math.orig.trunc(obj);
};
abs
Returns the absolute value of a number.
math.abs = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.abs);
}
return math.orig.abs(obj);
};
add
Adds a value to each element of an array.
math.add = function(obj, summand){
if(math.isArray(obj)){
return obj.map(i => math.add(i, summand));
}
return obj + summand;
};
subtract
Subtracts a value from each element of an array.
math.subtract = function(obj, subtrahend){
if(math.isArray(obj)){
return obj.map(minuend => math.subtract(minuend, subtrahend));
}
return obj - subtrahend;
};
multiply
AKA scale
Multiplies by a scalar.
math.multiply = math.scale = function(obj, scalar){
if(math.isArray(obj)){
return obj.map(i => math.scale(i, scalar));
}
return obj * scalar;
};
scale01
Transforms an array to fit within the range [0, 1], such that the ratios between any two pairs of elements are maintained.
math.scale01([0, 2, 5, 10])
⇒ [0, 0.2, 0.5, 1]
math.scale01 = function(obj, key){
var arr = math.pluck(obj, key);
return math.scalemm(arr, 0, 1);
};
scale11
Transforms an array to fit within the range [-1, 1], such that the ratios between any two pairs of elements are maintained.
math.scale11([0, 2, 5, 10])
⇒ [-1, -0.6, 0, 1]
math.scale11 = function(obj, key){
var arr = math.pluck(obj, key);
return math.scalemm(arr, -1, 1);
};
scale0100
Transforms an array to fit within the range [0, 100], such that the ratios between any two pairs of elements are maintained.
math.scale11([0, 2, 5, 10])
⇒ [-1, -0.6, 0, 1]
math.scale0100 = function(obj, key){
var arr = math.pluck(obj, key);
return math.scalemm(arr, 0, 100);
};
scalemm
Transforms an array to fit within the range [min, max], such that the ratios between any two elements are maintained.
math.scalemm([0, 2, 5, 10])
⇒ [-1, -0.6, 0, 1]
math.scalemm = math.scaleMM = function(obj, min, max){
if(math.isUndefined(min)) min = 0;
if(math.isUndefined(max)) max = 1;
var minArr = math.min(obj),
oldRange = math.max(obj) - minArr,
newRange = max - min;
return obj.map(i => (i - minArr) / oldRange * newRange + min);
};
divide
Divides each element in obj
by divisor
.
math.divide = function(obj, divisor){
if(math.isArray(obj)){
return obj.map(dividend => math.divide(dividend, divisor));
}
return obj / divisor;
};
modulo
Divides each element in obj
by divisor
, and returns the remainder.
math.modulo = function(obj, divisor){
if(math.isArray(obj)){
return obj.map(dividend => math.modulo(dividend, divisor));
}
return obj % divisor;
};
pow
Given a number and an exponent, returns the number raised to the exponent.
Given an array of numbers, along with an exponent, returns an array for which each entry is the corresponding value of the original array raised to that exponent.
Given an array of objects, should fail. If you need to raise an array of
objects to an exponent, please use math.square
, math.cube
, math.sqrt
,
and math.cbrt
for n = 2, 3, 1/2, and 1/3 respectively. For arbitrary
values of n, please call math.pluck
your array first, and pass the
plucked array to math.pow
.
math.pow(2,3)
⇒ 8
math.pow([1, 2, 10], 3)
⇒ [1, 8, 1000]
math.pow = function(obj, exponent){
if(math.isArray(obj)){
return obj.map(i => math.pow(i, exponent));
}
return math.orig.pow(obj, exponent);
};
Note that the following functions will accept arrays of objects, where math.pow will not.
square
Multiplies a number by itself.
math.square = function(obj, key){
return math.pow(math.pluck(obj, key), 2);
};
cube
Multiplies a number by its square.
math.cube = function(obj, key){
return math.pow(math.pluck(obj, key), 3);
};
sqrt
Given a number, computes the Square Root
math.sqrt = function(obj, key){
return math.pow(math.pluck(obj, key), 1/2);
};
cbrt
Given a number, computes the Cube Root
math.cbrt = function(obj, key){
return math.pow(math.pluck(obj, key), 1/3);
};
exp
Given a number x, computes e^x where e is Euler’s natural base.
math.exp = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.exp);
}
return math.pow(math.orig.E, obj);
};
expm1
Given a number x, computes e^x-1 where e is Euler’s natural base.
math.expm1 = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.expm1);
}
return math.pow(math.orig.E, obj) - 1;
};
log
Computes the natural logarithm of a number.
math.log = math.ln = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.log);
}
return math.orig.log(obj);
};
log1p
Given a number x, computes the natural logarithm of x + 1
math.log1p = math.ln1p = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.log1p);
}
return math.log(1 + obj);
};
log10
Computes the logarithm base 10 of a number.
math.log10 = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.log10);
}
return math.orig.log10(obj);
};
log2
Computes the logarithm base 2 of a number.
math.log2 = math.lg = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.log2);
}
return math.orig.log2(obj);
};
logb
Computes the logarithm base b of an object (or each element within it)
math.logb = function(obj, base){
var b = math.log(base);
if(math.isArray(obj)){
return obj.map(x => math.log(x)/b);
}
return math.log(obj)/b;
};
factorial
Given a number, computes the factorial.
math.factorial = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.factorial);
}
if(obj < 0){
return Infinity;
} else if(obj === 0){
return 1;
} else {
return math.product(math.range(obj));
}
};
permute
Returns the number of distinct, ordered arrays of size r
from obj
elements.
math.permute = math.permutations = function(obj, r){
if(math.isArray(obj)){
return obj.map(math.permute);
}
return math.factorial(obj)/math.factorial(obj - r);
};
choose
Returns the number of distinct, unordered sets of size r
from obj
elements.
math.choose = math.combinations = function(obj, r){
if(math.isArray(obj)){
return obj.map(math.choose);
}
return math.permute(obj, r)/math.factorial(r);
};
copySign
Given a number, copies the sign of b onto obj
Given an Array, copies the sign of b onto each value of obj
math.copySign = math.copysign = function(obj, b){
if(math.isArray(obj)){
return obj.map(i => math.copySign(i, b));
}
return math.isSameSign(obj, b) ? obj : -obj;
};
undirectedEdges
Computes the maximum number of distinct edges of an undirected graph of n
nodes.
math.undirectedEdges = math.undirectededges = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.undirectedEdges);
}
return obj * (obj - 1) / 2;
};
factors
Returns an array of the factors of a number, n
math.factors = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.factors);
}
var result = [],
startN = math.abs(math.round(obj)),
finished = false;
while(!finished){
finished = true;
for (var i = 2; i <= startN / 2; i++){
if(obj % i === 0){
obj /= i;
result.push(i);
finished = false;
break;
}
}
}
if(result.length === 0){
result.push(startN);
}
return result;
};
divisors
Returns an array of the divisors of a number n
math.divisors = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(math.divisors);
}
var safeN = math.abs(math.round(obj)),
result = [1];
for(var i = 2; i <= safeN / 2; i++){
if(safeN % i === 0){
result.push(i);
}
}
return result;
};
between
Returns a boolean indicating whether a number x is between two others numbers, a and b.
math.between = function (obj, a, b){
if(math.isArray(obj)){
return obj.map(i => math.between(i, a, b));
}
return (a<=obj && obj<=b) || (b<=obj && obj<=a);
};
format
Truncates a number n at the given precision
math.format([1.234, 2.345], 2)
⇒ [1.2, 2.3]
math.format = function(obj, precision){
if(math.isArray(obj)){
return obj.map(i => math.format(i, precision));
}
return (obj.toFixed(precision))/1;
};
sort
Given an array of numbers, returns the array sorted.
Warning: This implements an in-place algorithm.
math.sort([3,1,2])
⇒ [1,2,3]
math.sort = function(obj, descending){
if(descending){
return obj.sort((a, b) => b - a);
} else {
return obj.sort((a, b) => a - b);
}
};
zScore
Computes the standard Z-score, assuming a normal distribution.
math.zScore([1,2,3])
⇒ [-1.224744871391589, 0, 1.224744871391589]
math.zScore = math.zscore = function(obj, key){
var arr = math.pluck(obj, key),
mean = math.mean(arr),
sigma = math.stdDeviation(arr);
return arr.map(d => (d-mean)/sigma);
};
Trigonometry
Performs trigonometric computations.
['sin', 'sinh', 'cos', 'cosh', 'tan', 'tanh', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh'].forEach(fun => {
math[fun] = function(obj, key){
if(math.isArray(obj)){
return math.pluck(obj, key).map(i => math[fun](i));
}
return math.orig[fun](obj);
};
});
atan2
Returns the arctangent of the quotient of each element of obj
and
divisor
math.atan2 = function(obj, divisor){
return math.atan(math.divide(obj, divisor));
};
Reducers
Reducers are functions which accept an array and return (usually) a singe
number. (Some, like math.movingAvg
will return a smaller array).
Perhaps the most recognizable reducer is the Arithmetic mean (more
commonly just called the “average”), though there are many other well-
known, simple reducers (as you can see from the list of functions between
this paragraph and math.mean
).
min
Computes the maximum of an array of numbers
math.maxArr([1,2,3])
⇒ 3
math.min = function(obj, key, ...others){
if(!math.isArray(obj)){
return math.orig.min(obj, key, ...others);
}
return math.orig.min(...math.pluck(obj, key));
};
max
Computes the maximum of an array of numbers
math.maxArr([1,2,3])
⇒ 3
math.max = function(obj, key, ...others){
if(!math.isArray(obj)){
return math.orig.max(obj, key, ...others);
}
return math.orig.max(...math.pluck(obj, key));
};
sum
Computes the sum of an array of numbers (or an array of objects with a
given key
).
math.sum([1,2,3])
⇒ 6
math.sum([{b: 4},{b: 5},{b: 6}], 'b')
⇒ 15
math.sum = function(obj, key){
return math.pluck(obj, key).reduce((a, b) => a + b, 0);
};
product
Computes the product of an array of numbers (or an array of objects with a
a given key
).
math.product([1,2,3])
⇒ 6
math.product([{b: 4},{b: 5},{b: 6}], 'b')
⇒ 120
math.product = function(obj, key){
return math.pluck(obj, key).reduce((a, b) => a * b, 1);
};
gcd
Determines the greatest common divisor between two numbers.
math.gcd = function(obj, b){
if(math.isArray(obj)){
return obj.map(i => math.gcd(i, b));
}
var ref;
while(b){
ref = [b, obj % b];
obj = ref[0];
b = ref[1];
}
return obj;
};
lcm
Determines the least common multiple of two numbers.
math.lcm = function(obj, b){
if(math.isArray(obj)){
return obj.map(i => math.lcm(i, b));
}
return obj / math.gcd(obj, b) * b;
};
mean
Given an array of numbers, returns the arithmetic mean.
math.mean([1,2,3])
⇒ 2
math.mean = math.average = function(obj, key){
var arr = math.pluck(obj, key);
return math.sum(arr) / arr.length;
};
median
Given an array of numbers, returns the median.
math.median([1,2,3,4])
⇒ 2.5
math.median = function(obj, key){
var arr = math.pluck(obj, key),
middle = (arr.length + 1) / 2,
sorted = math.sort(arr);
return (sorted.length % 2) ? sorted[middle - 1] : (sorted[middle - 1.5] + sorted[middle - 0.5]) / 2;
};
modes
Returns an array of the most frequently recurring value in the input array.
math.mode = math.modes = function(obj, key){
var arr = math.pluck(obj, key),
modeMap = {},
maxCount = 0,
modes = [];
arr.forEach(val => {
if(!modeMap[val]){
modeMap[val] = 1;
} else {
modeMap[val]++;
}
if(modeMap[val] > maxCount){
modes = [val];
maxCount = modeMap[val];
} else if(modeMap[val] === maxCount){
modes.push(val);
}
});
return modes;
};
geometricMean
Given an array of numbers, returns the geometric mean.
math.geometricMean([3,9,27])
⇒ 9
math.geometricMean = function(obj, key){
var arr = math.pluck(obj, key);
return math.pow(math.product(arr), 1 / arr.length);
};
midrange
Given an array of numbers, returns the midrange (the mean of the max and min of a set of numbers).
math.midrange([3,9,27])
⇒ 18
math.midrange = math.midRange = function(obj, key){
var arr = math.pluck(obj, key),
min = math.min(arr);
return ((math.max(arr) - min) / 2) + min;
};
Variance
Computes the variance of an array of numbers.
math.variance([1,2,3])
⇒ 2/3
math.variance = function(obj, key){
var arr = math.pluck(obj, key),
mean = math.mean(arr);
return math.mean(arr.map(x => math.pow(x - mean, 2)));
};
stdDeviation
Computes the Standard Deviation of an array of numbers.
math.stdDeviation([1,2,3])
⇒ 0.8165…
math.stdDeviation = math.sigma = function(obj, key){
return math.sqrt(math.variance(math.pluck(obj, key)));
};
meanAbsoluteDeviation
Computes the mean absolute deviation of an array of numbers.
math.meanAbsoluteDeviation([1,2,3])
⇒ 1
math.meanAbsoluteDeviation = function(obj, key){
var arr = math.pluck(obj, key),
mean = math.mean(arr);
return math.mean(arr.map(n => math.abs(n - mean)));
};
hypot
AKA rss
for “Root sum of squares”
Given any number of numbers (in an array or given as arbitrary arguments). returns the root sum of squares. For n numbers, this is equivalent to a hypotenuse in n-dimensional space.
math.hypot = math.rss = function(obj, key, ...others){
if(math.isArray(obj)){
var arr = math.pluck(obj, key);
if(math.isNumber(key)){
return math.hypot(...arr, key, ...others);
}
return math.hypot(...arr, ...others);
}
return math.orig.hypot(obj, key, ...others);
};
wilson
Given an array of boolean values and a Z-score, returns the Wilson Score Interval
Z-score is defaulted to cover the 95% interval.
math.wilson = function(obj, z){
var up = obj.reduce((x, i) => i ? x + 1 : x, 0),
total = obj.length;
if(total <= 0 || total < up) return 0;
var avg = up/total,
z = z || 1.644853,
z2 = math.square(z);
return (avg + z2/(2*total) - z*math.sqrt((avg*(1 - avg) + z2/(4*total))/total))/(1 + z2/total);
};
movingAverage
Computes a moving average of an array of numbers.
In case this is non-obvious, this should return an array of fewer elements than the original array contained.
math.movingAvg([1,2,3,4,5], 3)
⇒ [2,3,4]
math.movingAverage = math.movingaverage = math.movingAvg = function(obj, size){
var win, newarr = [];
for(var i = size - 1; i <= obj.length; i++){
win = obj.slice(i - size, i);
if(win.length === size){
newarr.push(math.mean(win));
}
}
return newarr;
};
Fin
if(typeof exports !== 'undefined'){
if(typeof module !== 'undefined' && module.exports){
exports = module.exports = math;
}
exports.math = math;
} else {
window.math = math;
}
}).call();