@obliczeniowo/elementary
Version:
Library made in Angular version 20
296 lines (293 loc) • 9.96 kB
JavaScript
class ElementaryMath {
/**
* Calc modulo of two decimal places numbers
*/
static fmod(value, base) {
return value - Math.floor(value / base) * base;
}
static radiansToDegrees(angle) {
return angle * 180 / Math.PI;
}
static degreesToRadians(angle) {
return angle * Math.PI / 180;
}
static minmax(value, min, max) {
return value < min ? min : value > max ? max : value;
}
static getMinMax(array) {
if (array.length) {
const minMax = { min: array[0], max: array[0] };
array.forEach(v => {
if (v > minMax.max) {
minMax.max = v;
}
if (v < minMax.min) {
minMax.min = v;
}
});
return minMax;
}
return { min: NaN, max: NaN };
}
/**
* Check if string is number
* @param n number/string to check if number
* @param fully if true will tests if string contain only number format like:
*
* -1432
* -123.45
* -123.45e10
* -123.45e-10
* 123.45e-10
* 123.45e10
* 123.45
* 123
*
* format 123.45e is not proper number so it is not consider as number, as well as:
*
* 123 some string
* some string 123
* 123..
* 123.123.
* 123e-10e-10
*
* @returns true if is number (not NaN or infinity)
*/
static isNumeric(n, fully = false) {
if (typeof n === 'number') {
return !isNaN(n) && isFinite(n);
}
if (fully) {
const reg = /^-?\d*\.?\d*e?-?\d{1,}$/;
if (!reg.test(n)) {
return false;
}
}
return !isNaN(parseFloat(n));
}
static precision(value) {
return (value - Math.floor(value)) < 0.5 && Math.floor(value) || Math.ceil(value);
}
static average(values) {
return values.reduce((p, c) => (p += c, p), 0) / values.length;
}
static standardDeviation(values) {
const average = ElementaryMath.average(values);
return Math.sqrt(values.reduce((p, c) => (p += (c - average) * (c - average), p), 0) / values.length);
}
static averageAndStandardDeviation(values) {
const middle = ElementaryMath.average(values);
return {
middle,
standardDeviation: Math.sqrt(values.reduce((p, c) => (p += (c - middle) * (c - middle), p), 0) / values.length)
};
}
static normalization(values) {
const params = ElementaryMath.averageAndStandardDeviation(values);
return values.map(value => (value - params.middle) / (params.standardDeviation || 1));
}
/**
* Calc how many times each unique value exist in table of numbers
* @param values numeric values to count
* @returns Map object to collect counted times numeric values as key: value, value: count
*
* @example
*
* countUnique([10, 10, 10, 20, 20, 30])
*
* return: Map(3) { 10 → 3, 20 → 2, 30 → 1 }
*/
static countUnique(values) {
const map = new Map();
values.forEach(value => {
map.set(value, map.has(value) ? (map.get(value) || 1) + 1 : 1);
});
return map;
}
/**
* Calc weighted average
* @param values values table
* @param weights weights table
* @returns calculated average if values.length === weights.length, else NaN
*/
static averageWeighted(values, weights) {
if (values.length !== weights.length) {
return NaN;
}
else if (values.length) {
return values.reduce((p, c, index) => (p += c * weights[index], p), 0) / (weights.reduce((p, c) => (p += c, p), 0) || 1);
}
return 0;
}
/**
* Pick up n% position of sorted array of numbers
* @param percentages table of percentage as for example [10, 20, 30, 40, 50]
* @param values table of numeric values [5, 10, 15, 20, 20, 20, 20, 20, 50, 60]
* @returns for given above inputs [10, 15, 20, 20, 20]
*/
static percentagesByPosition(percentages, values) {
values = values.sort((a, b) => a - b);
return percentages.map(percentage => values[Math.floor(values.length * percentage / 100)]);
}
/**
* Calc sum of values and divide all elements by it and multiply by multiplier
* @param values vector of numbers [100, 200, 300, 400, 1000]
* @param multiply by default 100 to get percentages
* @returns for given input [5, 10, 15, 20, 50] as percentages
*/
static percentagesBySum(values, multiply = 100) {
const sum = ElementaryMath.sum(values);
return values.map(value => value / sum * multiply);
}
/**
* Find abs max value in values numbers vector and divide each value by it and multiply by 100
* @param values example: [10, 20, 30, 200, 40, 20, -400]
* @param multiply multiplier example: 100
* @returns [2.5, 5, 7.5, 50, 10, 5, -100]
*/
static percentageByAbsMax(values, multiply = 100) {
const max = values.reduce((p, c, index) => (p = !index ? c : ElementaryMath.absMax(p, c), p));
return values.map(value => value / max * multiply);
}
/**
* Find max value in values numbers vector and divide each value by it and multiply by 100
* @param values example: [10, 20, 30, 200, 40, 20, -400]
* @param multiply multiplier example: 100
* @returns [5, 10, 15, 100, 20, 10, -200]
*/
static percentageByMax(values, multiply = 100) {
const max = values.reduce((p, c, index) => (p = !index ? c : Math.max(p, c), p));
return values.map(value => value / max * multiply);
}
static sum(values) {
return values.reduce((p, c) => p += c, 0);
}
static absMax(a, b) {
return Math.abs(a) < Math.abs(b) ? b : a;
}
static calculate(val, variables) {
if (val instanceof Array) {
const rec = val.map(v => ElementaryMath.calculate(v, variables));
switch (rec[0]) {
case 'get': {
return variables[rec[1].toString()];
}
case '*':
case 'multiply': {
return (rec.slice(1).reduce((p, c) => (p *= c, p), 1));
}
case '/':
case 'divide': {
return (rec[1] / rec[2]);
}
case '+':
case 'add': {
return (rec.slice(1).reduce((p, c) => (p += c, p), 0));
}
case '-':
case 'subtract': {
return (rec[1] - rec[2]);
}
case 'mod': {
return (rec[1] % rec[2]);
}
case 'exp': {
return Math.exp(rec[1]);
}
case 'pow': {
return Math.pow(rec[1], rec[2]);
}
case 'sin': {
return Math.sin(rec[1]);
}
case 'cos': {
return Math.cos(rec[1]);
}
case 'tan': {
return Math.tan(rec[1]);
}
case 'atan': {
return Math.atan(rec[1]);
}
case 'acos': {
return Math.acos(rec[1]);
}
case 'asin': {
return Math.asin(rec[1]);
}
case 'sinh': {
return Math.sinh(rec[1]);
}
case 'cosh': {
return Math.cosh(rec[1]);
}
case 'tanh': {
return Math.tanh(rec[1]);
}
case 'asinh': {
return Math.asinh(rec[1]);
}
case 'acosh': {
return Math.acosh(rec[1]);
}
case 'atanh': {
return Math.atanh(rec[1]);
}
case 'or': {
return (rec[1] || rec[2]);
}
case 'and': {
return (rec[1] && rec[2]);
}
case 'not': {
return (!rec[1]);
}
case '==': {
return (rec[1] == rec[2]);
}
case '!=': {
return (rec[1] != rec[2]);
}
case '<': {
return (rec[1] < rec[2]);
}
case '<=': {
return (rec[1] <= rec[2]);
}
case '>': {
return (rec[1] > rec[2]);
}
case '>=': {
return (rec[1] >= rec[2]);
}
case 'toRadians': {
return ElementaryMath.degreesToRadians(rec[1]);
}
case 'toDegrees': {
return ElementaryMath.degreesToRadians(rec[1]);
}
case 'join': {
return rec.slice(1).map(v => v.toString()).join('');
}
case 'pi': {
return Math.PI;
}
case 'e': {
return Math.E;
}
case 'if-else': {
return rec[1] ? rec[2] : rec[3];
}
case 'goldenRatio': {
return 1.618033988749894;
}
}
}
return val;
}
}
/**
* Generated bundle index. Do not edit.
*/
export { ElementaryMath };
//# sourceMappingURL=obliczeniowo-elementary-math.mjs.map