解决js数字运算精度问题-bignumber.js

一个用于任意精度小数和非小数运算的 JavaScript 库

地址:https://github.com/MikeMcl/bignumber.js

功能

  •  整数和小数
  •  简单的 API,但功能齐全
  • 比 Java 的 BigDecimal 的 JavaScript 版本更快、更小,而且可能更容易使用
  •  大小只有8 KB 
  • 支持密码安全的伪随机数生成
  • 没有依赖性
  • 广泛的平台兼容性: 仅使用 JavaScript 1.5(ECMAScript 3)特性

 浏览器:

<script src='path/to/bignumber.js'></script>

Node.js

​​​​​​​$ npm install bignumber.js
const BigNumber = require('bignumber.js');
import BigNumber from "bignumber.js";
// or
import { BigNumber } from "bignumber.js";

 使用

单个构造函数 BigNumber,该函数接受 Number、 String 或 BigNumber 类型的值,

let x = new BigNumber(123.4567);
let y = BigNumber('123456.7e-3');
let z = new BigNumber(x);
x.isEqualTo(y) && y.isEqualTo(z) && x.isEqualTo(z);      // true

要获取 BigNumber 的字符串值,可以使用 toString ()或 toFixed ()。使用 toFixed ()可以防止返回指数表示法,无论值有多大或多小。

let x = new BigNumber('1111222233334444555566');
x.toString();                       // "1.111222233334444555566e+21"
x.toFixed();                        // "1111222233334444555566"

如果没有很好地理解 Number 值的有限精度,建议从 String 值而不是 Number 值创建 BigNumbers,以避免可能的精度损失。

在下面所有进一步的示例中,不显示分号和 toString 调用。如果注释掉的值在引号中,则表示对前面的表达式调用了 toString。

// Precision loss from using numeric literals with more than 15 significant digits.
new BigNumber(1.0000000000000001)         // '1'
new BigNumber(88259496234518.57)          // '88259496234518.56'
new BigNumber(99999999999999999999)       // '100000000000000000000'

// Precision loss from using numeric literals outside the range of Number values.
new BigNumber(2e+308)                     // 'Infinity'
new BigNumber(1e-324)                     // '0'

// Precision loss from the unexpected result of arithmetic with Number values.
new BigNumber(0.7 + 0.1)                  // '0.7999999999999999'

从 Number 创建 BigNumber 时,请注意 BigNumber 是从 Number 的十进制 toString ()值创建的,而不是从其基础二进制值创建的。如果需要后者,则传递 Number 的 toString (2)值并指定 base 2。

new BigNumber(Number.MAX_VALUE.toString(2), 2)

BigNumbers 可以从2到36的基数值中创建。请参见 ALPHABET 以扩展这个范围。

a = new BigNumber(1011, 2)          // "11"
b = new BigNumber('zz.9', 36)       // "1295.25"
c = a.plus(b)                       // "1306.25"

如果不为十进制值指定基数10,性能会更好。只有当您希望将输入值的小数位数限制为当前 DECIMAL _ places 设置时,才指定 base 10。

BigNumber 是不可变的,因为它的方法不会改变它。

0.3 - 0.1                           // 0.19999999999999998
x = new BigNumber(0.3)
x.minus(0.1)                        // "0.2"
x                                   // "0.3"

返回 BigNumber 的方法可以链接起来。

x.dividedBy(y).plus(z).times(9)
x.times('1.23456780123456789e+9').plus(9876.5432321).dividedBy('4444562598.111772').integerValue()

一些较长的方法名有较短的别名。

x.squareRoot().dividedBy(y).exponentiatedBy(3).isEqualTo(x.sqrt().div(y).pow(3))    // true
x.modulo(y).multipliedBy(z).eq(x.mod(y).times(z))                                   // true

和 JavaScript 的 Number 类型一样,有 toExponential、 toFixed 和 toPrecision 方法。

x = new BigNumber(255.5)
x.toExponential(5)                  // "2.55500e+2"
x.toFixed(5)                        // "255.50000"
x.toPrecision(5)                    // "255.50"
x.toNumber()                        //  255.5

可以为 toString 指定基。

 

如果没有指定基数10,性能会更好,即使用 toString ()而不是 toString (10)。只有当您希望将字符串的小数位数限制为当前 DECIMAL _ places 设置时,才指定 base 10。

x.toString(16)                     // "ff.8"

有一个 toFormat 方法可能对国际化很有用。

y = new BigNumber('1234567.898765')
y.toFormat(2)                       // "1,234,567.90"

 

使用 BigNumber 构造函数的 set 或 config 方法设置涉及除法(即除法、平方根、基转换或负功率运算)的运算结果的最大小数位数。

其他的算术运算总是给出精确的结果。

BigNumber.set({ DECIMAL_PLACES: 10, ROUNDING_MODE: 4 })

x = new BigNumber(2)
y = new BigNumber(3)
z = x.dividedBy(y)                        // "0.6666666667"
z.squareRoot()                            // "0.8164965809"
z.exponentiatedBy(-3)                     // "3.3749999995"
z.toString(2)                             // "0.1010101011"
z.multipliedBy(z)                         // "0.44444444448888888889"
z.multipliedBy(z).decimalPlaces(10)       // "0.4444444445"

有一个带有可选最大分母参数的 toFraction 方法

y = new BigNumber(355)
pi = y.dividedBy(113)               // "3.1415929204"
pi.toFraction()                     // [ "7853982301", "2500000000" ]
pi.toFraction(1000)                 // [ "355", "113" ]

以及 isNaN 和 isFinite 方法,因为 NaN 和 Infinity 是有效的 BigNumber 值。

x = new BigNumber(NaN)                                           // "NaN"
y = new BigNumber(Infinity)                                      // "Infinity"
x.isNaN() && !y.isNaN() && !x.isFinite() && !y.isFinite()        // true

BigNumber 的值以系数、指数和符号的十进制浮点格式存储。

x = new BigNumber(-123.456);
x.c                                 // [ 123, 45600000000000 ]  coefficient (i.e. significand)
x.e                                 // 2                        exponent
x.s                                 // -1                       sign

对于高级用法,可以创建多个 BigNumber 构造函数,每个构造函数都有自己的独立配置。

// Set DECIMAL_PLACES for the original BigNumber constructor
BigNumber.set({ DECIMAL_PLACES: 10 })

// Create another BigNumber constructor, optionally passing in a configuration object
BN = BigNumber.clone({ DECIMAL_PLACES: 5 })

x = new BigNumber(1)
y = new BN(1)

x.div(3)                            // '0.3333333333'
y.div(3)                            // '0.33333'

为了避免在 BigNumber 上调用 toString 或 valueOf 来获取其在 Node.js REPL 中的值,或者在使用 console.log 时使用

BigNumber.prototype[require('util').inspect.custom] = BigNumber.prototype.valueOf;

猜你喜欢

转载自blog.csdn.net/liuhao9999/article/details/113698908
今日推荐