@ou-imdt/utils
Version:
Utility library for interactive media development
87 lines (74 loc) • 1.88 kB
JavaScript
/**
* 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);
}
}