UNPKG

@obliczeniowo/elementary

Version:
296 lines (293 loc) 9.96 kB
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