Big numbers with fraction support:
I want to perform math operation with no precision loss.
How can I do it using JavaScript?
First I tried decimal.js, but it does not preserve precision as you see in next example:
import {Decimal} from 'decimal.js';
const a1 = new Decimal(1);
const a2 = new Decimal(3);
console.log(a1.div(a2).toFraction()); // should be `1/3` but I get `33333333333333333333/100000000000000000000`
Next I tried fraction.js but it does not work with large numbers, for example:
import Fraction from 'fraction.js';
const n1 = new Fraction("99999999999999999999999999999999999999999999999");
const n2 = new Fraction("99999999999999999999999999999999999999999999990");
console.log(+(n1.sub(n2))) // should be 9, but I get 0
Are there any solutions to work with relative large numbers(lets say same as decimal.js
supports) but with high precision(same as fraction.js
supports).
I checked out that mathjs
uses fraction.js
under the hood, so no any advantages for large numbers:
import * as math from "mathjs";
const a1 = math.fraction(math.number("99999999999999999999999999999999999999999999999"))
const a2 = math.fraction(math.number("99999999999999999999999999999999999999999999990"))
console.log(+(math.subtract(a1, a2))) // should be 9 but I get 0
2
Answers
That’s more like a bug you found in
decimal.js
. If you manually provide the maximum denominator argument, it produces 1/3.https://github.com/MikeMcl/decimal.js/issues seems to be where this could be reported.
Given that JavaScript has a BigInt data type, it is not so hard to implement the basic arithmetic operations yourself. Most logic will be needed in the constructor so to normalise the fraction (denominator should not be negative, numerator and denominator should be coprime) and deal with type conversion.
For example: