BigNumbers #

对于任意精度的计算,math.js 支持 BigNumber 数据类型。BigNumber 支持由 decimal.js 提供支持。

用法 #

可以使用 bignumber 函数创建 BigNumber。

math.bignumber('2.3e+500') // BigNumber, 2.3e+500

大多数函数可以根据输入类型确定输出类型:输入数字则输出数字,输入 BigNumber 则输出 BigNumber。无法根据输入确定输出类型的函数(例如 math.evaluate)会使用默认数字类型 number,该类型可在实例化 math.js 时进行配置。要将 BigNumbers 配置为默认值而不是 numbers,请按如下方式配置 math.js:

math.config({
  number: 'BigNumber',      // Default type of number:
                            // 'number' (default), 'BigNumber', or 'Fraction'
  precision: 64,            // Number of significant digits for BigNumbers
  relTol: 1e-60,
  absTol: 1e-63
})

// use math
math.evaluate('0.1 + 0.2')  // BigNumber, 0.3

BigNumber 的默认精度为 64 位数字,可以通过 precision 选项进行配置。

请注意,我们还修改了 relTolabsTol 的配置,使其接近 BigNumbers 的精度限制。 relTolabsTol 用于例如关系和舍入函数(equal, larger, smaller, round, floor 等)来确定值何时接近相等,请参见 Equality。如果我们保持 relTolabsTol 不变(默认值分别为 1e-121e-15),由于我们现在使用更高的精度进行工作,我们可能会得到不准确和误导性的结果。

支持 #

math.js 中的大多数函数都支持 BigNumbers,但并非全部。例如 random 函数不支持 BigNumbers。

舍入误差 #

BigNumber 的计算比 Number 的计算慢得多,但它们可以以任意精度执行。通过使用更高的精度,不太可能发生舍入误差。

// 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

局限性 #

需要认识到 BigNumbers 并非能解决所有与精度和舍入误差相关的问题。具有无限小数位数的数字既不能用常规数字表示,也不能用 BigNumber 表示。尽管 BigNumber 可以存储更多的位数,但数字的位数仍然是有限的,即使是为了保持计算速度足够快以保持实用性。

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

转换 #

可以使用 numberbignumber 函数在 BigNumbers 和 numbers 之间进行转换。将 BigNumber 转换为 number 时,BigNumber 的高精度将丢失。当 BigNumber 大到无法表示为 Number 时,它将被初始化为 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
Fork me on GitHub