编程开发中有时候用到很大的数字的时候,语言本身的数字上限已经不能支持,此时只能自己构建一些数据结构去保存这些。JavaScript的Number
类型为双精度IEEE 754 64位浮点类型,一般来讲程序开发,基本的数字类型Number类型是够用的JavaScript 中最大的安全整数 (2的53次方 - 1
)和JavaScript 中最小的安全整数 (-(2的53次方 - 1)
)。但是有时候我们处理的业务逻辑出现秒产出和每个级别升级收益指数级增长的时候这个就超出了安全整数范围,此时我们一般借助于第三方类库(bignumber.js)和decimal.js 解决问题。
介绍
bignumber.js 一个用于任意精度算术的JavaScript库。官网文档是英文版的,作为一个中文开发者,简单的翻译一下这些方法是必不可少的工作。
静态方法
clone()
生成一个独立的BigNumber构造函数
1 | var num = BigNumber.clone() |
config()
为这个独立的BigNumber构造函数设置参数
包括以下几个参数:
- DECIMAL_PLACES(默认值:20) 用于设置小数位数。在除法、开方、指数计算时会用到。
1 | var num = BigNumber.clone() |
- ROUNDING_MODE(默认值4) 舍入模式,取值的意义可参照 文档
1 | var num = BigNumber.clone() |
1 | //取值范围: |
EXPONENTIAL_AT(默认值[-7,20]) 指数计数法
RANGE(默认值[-1e+9,1e+9])
CRYPTO(默认值 false) 用于设置BigNumber.random()的随机生成算法。如果无法设置为true,则使用Math.random()生成随机值。
MODULO_MODE(默认值:ROUND_DOWN) 取模运算的模式
POW_PRECISION(默认值:0) pow运算结果的精度
FORMATE(格式化对应的设置)
1 | 默认值: |
是否为大数字类型 isBigNumber
1 | x = 42 |
maximum([]),minimum([])
获取数组中的最大值/最小值
random([precision])
返回一个伪随机值,参数可以指定小数点位数
求和 .sum(n…) ⇒ BigNumber
1 | x = new BigNumber('3257869345.0378653') |
实例方法
绝对值.abs() *⇒ BigNumber*
返回一个BigNumber,其值是该BigNumber的值的绝对值,即大小。
返回值始终是精确且未取整的。
1 | x = new BigNumber(-0.8) |
加法:.plus(n [, base]) ⇒ BigNumber
1 | 0.1 + 0.2 // 0.30000000000000004 |
减法:.minus(n [, base]) ⇒ BigNumber
1 | 0.6 * 3 // 1.7999999999999998 |
除法
普通除法运算: .div(n [, base]) ⇒ BigNumber; .dividedBy(n [, base]) ⇒ BigNumber
1 | x = new BigNumber(355) |
注意: 除法计算结果会根据DECIMAL_PLACES和ROUNDING_MODE两个属性设置进行舍入。
除法,返回整数: .idiv(n [, base]) ⇒ BigNumber;.dividedToIntegerByv(n [, base]) ⇒ BigNumber
1 | x = new BigNumber(355) |
取模/取余: .mod(n [, base]) ⇒ BigNumber;modulo.(n [, base]) ⇒ BigNumber
1 | 1 % 0.9 // 0.09999999999999998 |
注意: 取模/取余运算受MODULO_MODE设置影响
指数运算: .pow(n [, m]) ⇒ BigNumber;.exponentiatedBy(n [, m]) ⇒ BigNumber
1 | Math.pow(0.7, 2) // 0.48999999999999994 |
注意: n代表的是指数。如果n<0,计算结果肯定是小数,所以计算结果会受 DECIMAL_PLACES 和 ROUNDING_MODE影响。
开平方:.sqrt() ⇒ BigNumber;.squareRoot.() ⇒ BigNumber
1 | x = new BigNumber(16) |
比较大小: .comparedTo(n [, base]) ⇒ number
比较结果,参考如下表:
1 | 1 操作数>n |
举例:
1 | x = new BigNumber(Infinity) |
大于 .gt(n [, base]) ⇒ boolean`
n
:number | string | BigNumberbase
:数字
有关更多参数详细信息,请参见BigNumber。
返回true
如果BigNumber的值比的值 n
,否则返回false
。
注意:此方法在comparedTo
内部使用该方法。
大于等于.gte(n [, base]) ⇒ boolean`
n
:number | string | BigNumberbase
:数字
有关更多参数详细信息,请参见BigNumber。
返回true
如果BigNumber的值大于或等于的值n
,否则返回false
。
注意:此方法在comparedTo
内部使用该方法。
小于.lt(n [, base]) *⇒ boolean*
n
:number | string | BigNumberbase
:数字
有关更多参数详细信息,请参见BigNumber。
返回true
如果BigNumber的值小于的值 n
,否则返回false
。
注意:此方法在comparedTo
内部使用该方法。
小于等于 .lte(n [, base]) *⇒ boolean*
n
:number | string | BigNumberbase
:数字
有关更多参数详细信息,请参见BigNumber。
返回true
如果此BigNumber的值小于或等于的值 n
,否则返回false
。
注意:此方法在comparedTo
内部使用该方法。
判断是否相等 .eq(n [, base]) ⇒ boolean`
n
:number | string | BigNumberbase
:数字
精度调整
.dp([dp [, rm]]) ⇒ BigNumber|number;decimalPlaces.[dp [, rm]]) ⇒ BigNumber|number 根据dp(decimals places)和rm(round mode)对操作数进行舍入
1 | x = new BigNumber(1234.56) |
取整:.integerValue([rm]) ⇒ BigNumber
根据rm(round mode)返回操作数的整数部分
1 | x = new BigNumber(123.456) |
有效数字 .sd([d [, rm]]) ⇒ BigNumber|number;precision.([d [, rm]]) ⇒ BigNumber|number
什么是有效数字?—>从该数的第一个非零数字起,直到末尾数字止的数字称为有效数字,如0.618的有效数字有三个,分别是6,1,8。
1 | x = new BigNumber(9876.54321) |
.toFixed([dp [, rm]]) ⇒ string
返回一个字符串,小数位根据dp截取或者填充。
注意: Unlike Number.prototype.toFixed, which returns exponential notation if a number is greater or equal to 1021, this method will always return normal notation.
跟Number.prototype.toFixed(dp)的异同
- 如果省略参数dp,BigNumber(1.123).toFixed() 原样返回’1.123’;而1.123.toFixed()会去掉所有小数位,只返回整数位’1’
- 如果操作数大于10^21,BigNumber(10^21).toFixed()会跟普通数字一样返回;10^21.toFixed() 会通过指数形式返回
1 | Math.pow(10,20).toFixed() //"100000000000000000000" |
示例:
1 | x = 3.456 |
注意: toFixed()方法与dp()方法的主要区别是,toFixed返回的是字符串,如果小数位不够的话会用0补齐;dp()方法返回的是BigNumber|number,小数位不够的话会忽略
数字格式化 .toFormat([dp [, rm]]) ⇒ string
返回字符串,会根据dp和rm进行舍入,并根据FORMAT属性进行格式化。
1 | format = { |
转换为js 基础数值类型 .toNumber() ⇒ number
效果与使用+运算符一致
1 | x = new BigNumber(456.789) |
平方根.sqrt() *⇒ BigNumber*
1 | x = new BigNumber(16) |
注意事项
- 如果大数字是很多位,则必须是字符串类型才行:比如
1 | 30000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000 |
官网解释:字符串* 类型的值的位数没有限制(JavaScript的最大数组大小除外)。请参阅RANGE
设置BigNumber的最大和最小可能指数值。
后续更新:
因为游戏算法里面涉及到了 指数运算 (bignumber.js)的指数计算的时候 幂 不能是小数,所以改成了 作者的另外一个大数字的库 decimal.js 用法基本一样,毕竟是一个作者的作品,如果你用的比较简单 他们还要 轻量版的
decimal.js-light (去掉了一些不常用的函数,文件更小)
这样 项目继续用大数字开发了,爽歪歪!!