BigNumbers #
For calculations with an arbitrary precision, math.js supports a BigNumber
datatype. BigNumber support is powered by
decimal.js.
Usage #
A BigNumber can be created using the function bignumber
:
math.bignumber('2.3e+500') // BigNumber, 2.3e+500
Most functions can determine the type of output from the type of input:
a number as input will return a number as output, a BigNumber as input returns
a BigNumber as output. Functions which cannot determine the type of output
from the input (for example math.evaluate
) use the default number type number
,
which can be configured when instantiating math.js. To configure the use of
BigNumbers instead of numbers by default, configure math.js like:
math.config({
number: 'BigNumber', // Default type of number:
// 'number' (default), 'BigNumber', or 'Fraction'
precision: 64, // Number of significant digits for BigNumbers
epsilon: 1e-60
})
// use math
math.evaluate('0.1 + 0.2') // BigNumber, 0.3
The default precision for BigNumber is 64 digits, and can be configured with
the option precision
.
Note that we also change the configuration of epsilon
to be close to the precision limit of our BigNumbers. epsilon
is used for
example in relational and rounding functions (equal
, larger
, smaller
,
round
, floor
, etc) to determine when a value is nearly equal,
see Equality. If we would leave epsilon
unchanged,
having the default value of 1e-12
, we could get inaccurate and misleading
results since we’re now working with a higher precision.
Support #
Most functions in math.js support BigNumbers, but not all of them.
For example the function random
doesn’t support BigNumbers.
Round-off errors #
Calculations with BigNumber are much slower than calculations with Number, but they can be executed with an arbitrary precision. By using a higher precision, it is less likely that round-off errors occur:
// round-off errors with numbers
math.add(0.1, 0.2) // Number, 0.30000000000000004
math.divide(0.3, 0.2) // Number, 1.4999999999999998
// no round-off errors with BigNumbers :)
math.add(math.bignumber(0.1), math.bignumber(0.2)) // BigNumber, 0.3
math.divide(math.bignumber(0.3), math.bignumber(0.2)) // BigNumber, 1.5
Limitations #
It’s important to realize that BigNumbers do not solve all problems related to precision and round-off errors. Numbers with an infinite number of digits cannot be represented with a regular number nor a BigNumber. Though a BigNumber can store a much larger number of digits, the amount of digits remains limited if only to keep calculations fast enough to remain practical.
const one = math.bignumber(1)
const three = math.bignumber(3)
const third = math.divide(one, three)
console.log(third.toString())
// outputs 0.3333333333333333333333333333333333333333333333333333333333333333
const ans = math.multiply(third, three)
console.log(ans.toString())
// outputs 0.9999999999999999999999999999999999999999999999999999999999999999
// this should be 1 again, but `third` is rounded to a limited number of digits 3
Conversion #
BigNumbers can be converted to numbers and vice versa using the functions
number
and bignumber
. When converting a BigNumber to a number, the high
precision of the BigNumber will be lost. When a BigNumber is too large to be represented
as Number, it will be initialized as Infinity
.
// converting numbers and BigNumbers
const a = math.number(0.3) // number, 0.3
const b = math.bignumber(a) // BigNumber, 0.3
const c = math.number(b) // number, 0.3
// exceeding the maximum of a number
const d = math.bignumber('1.2e500') // BigNumber, 1.2e+500
const e = math.number(d) // number, Infinity
// loosing precision when converting to number
const f = math.bignumber('0.2222222222222222222') // BigNumber, 0.2222222222222222222
const g = math.number(f) // number, 0.2222222222222222