Skip to content

配置与舍入模式

Decimal.set()(等价于 Decimal.config())修改全局默认配置,用 Decimal.clone() 创建独立配置的构造器。

1. 配置方法

js
Decimal.set({ precision: 5, rounding: 4 })   // 返回 Decimal 构造器本身(可链式)
Decimal.config({ precision: 5 })             // set 的别名,行为相同

三个入口:

方法作用
Decimal.set(config)修改默认构造器的配置(推荐写法)
Decimal.config(config)set 完全相同(别名)
Decimal.clone(config?)创建新的独立构造器,配置复制自当前构造器;不传参则完全复制
js
// 独立构造器示例
const Dec = Decimal.clone({ precision: 9, rounding: 1 });
new Dec(5).div(3)              // '1.66666666'(9 位)
new Decimal(5).div(3)          // 不受影响,仍按全局配置

NOTE

  • clone 出来的构造器实例仍然是 Decimal 的实例(new Dec(5) instanceof Decimaltrue)。
  • 不同构造器之间可以互相运算(自动转换),结果属于调用方构造器。
  • 配置是「进程级全局」的:set 会影响所有由该构造器创建的数字。

2. 配置项总表(默认值实测)

配置项类型取值范围默认值说明
precisionnumber1 ~ 1e920计算结果的最大有效数字位数
roundingnumber0 ~ 84舍入模式(见下表)
modulonumber0 ~ 91取模模式(见第 4 节)
toExpNegnumber0 ~ -9e15-7指数 ≤ 此值时 toString 用科学计数法
toExpPosnumber0 ~ 9e1521指数 ≥ 此值时 toString 用科学计数法
minEnumber-1 ~ -9e15-9e15低于此指数下溢为 0
maxEnumber1 ~ 9e159e15高于此指数溢出为 Infinity
cryptobooleantrue/falsefalserandom() 是否使用加密安全随机数
defaultsbooleantrue/false设为 true重置全部配置为默认值
js
// 全部配置
Decimal.set({
  precision: 50,
  rounding: Decimal.ROUND_HALF_EVEN,
  modulo: Decimal.EUCLID,
  toExpNeg: -10,
  toExpPos: 30,
  minE: -1e6,
  maxE: 1e6,
  crypto: true
});

// 一键恢复默认
Decimal.set({ defaults: true });
// 之后:precision=20, rounding=4, toExpNeg=-7, toExpPos=21, modulo=1, crypto=false

读取当前配置:直接读静态属性(也可直接赋值):

js
Decimal.precision    // 20
Decimal.rounding     // 4
Decimal.toExpNeg     // -7
Decimal.toExpPos     // 21
Decimal.minE         // -9000000000000000
Decimal.maxE         // 9000000000000000
Decimal.crypto       // false
Decimal.modulo       // 1

3. 舍入模式详解(rounding 0–8)

设结果需要截断到第 k 位,比较第 k+1 位:

常量名称行为例:对 2.5 取整
ROUND_UP0远离零一律向远离 0 的方向进 13
ROUND_DOWN1趋向零(截断)一律丢弃多余位2
ROUND_CEIL2向上向 +∞ 进 13
ROUND_FLOOR3向下向 -∞ 进 12
ROUND_HALF_UP4四舍五入(默认)舍入位 ≥5 进 13
ROUND_HALF_DOWN5五舍六入舍入位 >5 才进 12
ROUND_HALF_EVEN6银行家舍入恰好 .5 时取偶数邻居2
ROUND_HALF_CEIL7半数向上.5 时向 +∞3
ROUND_HALF_FLOOR8半数向下.5 时向 -∞2

NOTE

上表「例:对 2.5 取整」为理论值;注意 round() 方法无参数,仅按当前全局 rounding 工作(见 算术运算)。指定模式的舍入请用 toDP(n, mode) / toSD(n, mode) 等(见 格式化与输出)。

验证示例(用 toDP(0, mode) 指定模式对 1.5 / 2.5 取整,实测):

js
new Decimal('1.5').toDP(0, Decimal.ROUND_HALF_UP)     // '2'
new Decimal('1.5').toDP(0, Decimal.ROUND_HALF_EVEN)   // '2'
new Decimal('2.5').toDP(0, Decimal.ROUND_HALF_EVEN)   // '2'(.5 取偶数)
new Decimal('2.5').toDP(0, Decimal.ROUND_HALF_UP)     // '3'
new Decimal('2.5').toDP(0, Decimal.ROUND_DOWN)        // '2'
new Decimal('-2.5').toDP(0, Decimal.ROUND_CEIL)       // '-2'
new Decimal('-2.5').toDP(0, Decimal.ROUND_FLOOR)      // '-3'

货币场景最常用的两个模式:

js
// 四舍五入(默认):1.005 → 1.01
new Decimal('1.005').toFixed(2)                        // '1.01'
new Decimal('1.005').toFixed(2, Decimal.ROUND_DOWN)    // '1.00'(向下/截断,常用于折扣)

4. 取模模式(modulo 0–9)

a mod n 的符号取决于商 q = a / n 如何取整,余数 r = a - n × q

模式余数符号说明
ROUND_UP0与被除数相反较少用
ROUND_DOWN1与被除数相同默认,等价于 JS 的 %
ROUND_FLOOR3与除数相同等价于 Python 的 %
ROUND_HALF_EVEN6IEEE 754 的 remainder
EUCLID9恒为非负欧几里得除法,取模运算推荐
js
// 默认(modulo=1,同 JS %):余数符号跟随被除数
new Decimal(10).mod(3)       // '1'
new Decimal(-10).mod(3)      // '-1'
new Decimal(10).mod(-3)      // '1'
new Decimal(-10).mod(-3)     // '-1'

// 切换为 EUCLID:结果恒非负(-8 mod 3 = 1,8 mod -3 = 2)
Decimal.set({ modulo: Decimal.EUCLID });
new Decimal(-8).mod(3)       // '1'
new Decimal(8).mod(-3)       // '2'
Decimal.set({ modulo: 1 });

5. 指数显示配置示例

js
Decimal.set({ toExpPos: 30 });
new Decimal('1e21').toString()     // '1000000000000000000000'(不再是指数形式)
new Decimal('1e30').toString()     // '1e+30'
new Decimal('1e31').toString()     // '1e+31'
Decimal.set({ toExpNeg: -5 });
new Decimal('1e-7').toString()     // '1e-7'
new Decimal('1e-5').toString()     // '1e-5'
new Decimal('1e-4').toString()     // '0.0001'
Decimal.set({ defaults: true });   // 恢复

规则:指数 e >= toExpPose <= toExpNeg 时使用科学计数法。

6. crypto(加密随机数)

Decimal.set({ crypto: true }) 后,Decimal.random() 使用 crypto.getRandomValues 生成不可预测的随机数(若环境不支持会抛 [DecimalError] crypto unavailable)。详见 数学函数

7. 配置出错

js
Decimal.set({ precision: 0 })          // 抛错:[DecimalError] Invalid argument: precision: 0
Decimal.set({ precision: 1e9 + 1 })    // 抛错:[DecimalError] Invalid argument: precision: 1000000001

TIP

不要把全局配置改来改去:需要不同精度的场景,用 clone() 创建独立构造器,避免污染全局状态(详见 最佳实践与常见坑)。