If you don't want to think about having to call functions each time, you can create a Class that handles conversion for you.
class Decimal {
constructor(value = 0, scale = 4) {
this.intervalValue = value;
this.scale = scale;
}
get value() {
return this.intervalValue;
}
set value(value) {
this.intervalValue = Decimal.toDecimal(value, this.scale);
}
static toDecimal(val, scale) {
const factor = 10 ** scale;
return Math.round(val * factor) / factor;
}
}
Usage:
const d = new Decimal(0, 4);
d.value = 0.1 + 0.2; // 0.3
d.value = 0.3 - 0.2; // 0.1
d.value = 0.1 + 0.2 - 0.3; // 0
d.value = 5.551115123125783e-17; // 0
d.value = 1 / 9; // 0.1111
Of course, when dealing with Decimal there are caveats:
d.value = 1/3 + 1/3 + 1/3; // 1
d.value -= 1/3; // 0.6667
d.value -= 1/3; // 0.3334
d.value -= 1/3; // 0.0001
You'd ideally want to use a high scale (like 12), and then convert it down when you need to present it or store it somewhere. Personally, I did experiment with creating a UInt8Array and trying to create a precision value (much like the SQL Decimal type), but since Javascript doesn't let you overload operators, it just gets a bit tedious not being able to use basic math operators (+
, -
, /
, *
) and using functions instead like add()
, substract()
, mult()
. For my needs, it's not worth it.
But if you do need that level of precision and are willing to endure the use of functions for math, then I recommend the decimal.js library.
0.1
to a finite binary floating point number. – Kasiekask(new Number(0.1)).valueOf()
is0.1
. – Overglaze