UNPKG

@ou-imdt/utils

Version:

Utility library for interactive media development

87 lines (74 loc) 1.88 kB
/** * precise floating point calculation * @export * @class Decimal */ export default class DecimalModule { #value constructor(value) { this.#value = value; } get value() { return this.#value; } calc(value, operator) { const scale1 = this.#getScale(this.#value); const scale2 = this.#getScale(value); const power = (operator === '*') ? null : this.#getPower(scale1, scale2); const int1 = this.#getRoundInt(this.#value, power); const int2 = this.#getRoundInt(value, power); switch (operator) { case '+': this.#value = (int1 + int2) / power; break; case '-': this.#value = (int1 - int2) / power; break; case '*': { const power = this.#getPower(scale1 + scale2); this.#value = this.#getRoundInt(int1, int2) / power; break; } case '/': this.#value = int1 / int2; break; case '%': this.#value = (int1 % int2) / power; break; } return this; } add(value) { return this.calc(value, '+'); } minus(value) { return this.calc(value, '-'); } multiply(value) { return this.calc(value, '*'); } divide(value) { return this.calc(value, '/'); } remainder(value) { return this.calc(value, '%'); } round() { this.#value = Math.round(this.#value); // return this.calc(this.#value, ~); return this; } #getScale(value) { const [str, exponent = '0'] = `${value}`.split('e'); const decimal = `${str}`.split('.')[1] ?? ''; return decimal.length - Number(exponent); } #getPower(...args) { const exponent = (args.length === 1) ? args[0] : Math.max(...args); return Math.pow(10, exponent); } #getRoundInt(value, power) { power = power ?? this.#getPower(this.#getScale(value)); return Math.round(value * power); } }