big.js 上手教程(最全最详细)

big.js 上手教程(最全最详细)


一、概念与历史发展

1. 概念

big.js 是一个轻量级的 JavaScript 库,用于处理 高精度浮点数运算。它解决了 JavaScript 原生浮点数精度丢失的问题,适用于金融计算、科学计算等对精度要求极高的场景。

JS 浮点数问题示例:

0.1 + 0.2; // 0.30000000000000004 ❌ 精度错误

使用 big.js 后:

new Big(0.1).plus(0.2).toString(); // '0.3' ✅ 精确结果

2. 历史发展

  • 2014 年:由 MikeMcl 开发并开源,最初名为 BigNumber.js
  • 2018 年:更名为 big.js,成为 GitHub 上最受欢迎的高精度数字库之一
  • 特点:小巧(压缩后 < 5KB)、无依赖、兼容性好(支持 IE9+)
  • 适用领域:电商价格计算、银行利息结算、区块链交易、数据分析等

二、安装与引入方式

1. 安装(Node.js 环境)

npm install big.js
// 引入
const Big = require('big.js');

2. 浏览器中直接使用

<script src="https://cdn.jsdelivr.net/npm/[email protected]/big.min.js">script>
const result = new Big(123.456);

三、基本语法与 API

1. 创建 Big 实例

new Big(n: number | string | Big): Big
参数类型 示例 说明
数字 new Big(123.45) 推荐使用字符串避免精度丢失
字符串 new Big('123.45') 最推荐方式,确保精确解析
Big 对象 new Big(new Big(123)) 克隆

⚠️ 不建议传入复杂表达式或函数,应先转换为字符串或数字。


2. 常用方法一览

方法名 功能 示例
.plus(n) 加法 new Big(0.1).plus(0.2)
.minus(n) 减法 new Big(1.2).minus(0.7)
.times(n) 乘法 new Big(1.2).times(3)
.div(n[, dp]) 除法(可指定小数位) new Big(1).div(3, 2)
.mod(n) 取模 new Big(10).mod(3)
.pow(exp) 幂运算 new Big(2).pow(10)
.round(dp, rm) 四舍五入 new Big(3.14159).round(2)
.cmp(n) 比较 new Big(5).cmp(3)
.eq(n) 是否相等 new Big(5).eq(5)
.lt(n) / .lte(n) 小于 / 小于等于 new Big(2).lt(3)
.gt(n) / .gte(n) 大于 / 大于等于 new Big(5).gt(3)
.toNumber() 转换为原生 Number new Big(123).toNumber()
.toString() 输出字符串 new Big(123.456).toString()
.toFixed(dp) 格式化固定小数位 new Big(3.14159).toFixed(2)

四、配置项(全局设置)

你可以通过 Big.DPBig.RM 设置默认行为:

Big.DP = 20;    // 默认保留 20 位小数
Big.RM = 1;     // 舍入模式(0:四舍五入, 1:向下取整, 2:向上取整, 3:去尾法)

五、所有使用场景详解

场景 1:金融计算(加减乘除)

const amount1 = new Big('19.99');
const amount2 = new Big('5.49');

const total = amount1.plus(amount2); // '25.48'
console.log(total.toFixed(2)); // '25.48'

场景 2:货币汇率换算

// 导入Big.js库
import Big from 'big.js';

// 定义美元金额
const usd = new Big('100');

// 定义汇率(1美元兑换7.25人民币)
const rate = new Big('7.25'); // USD to CNY

// 计算等值人民币金额
const cny = usd.times(rate); // 结果将是'725.00'

// 输出结果,保留两位小数
console.log(cny.toFixed(2)); // 输出: '725.00'

场景 3:商品总价计算(带数量)

const price = new Big('29.99');
const quantity = 3;

const totalPrice = price.times(quantity); // '89.97'
console.log(totalPrice.toString());

场景 4:大额资金比较(安全风控)

const balance = new Big('1000000.00');
const withdrawal = new Big('999999.99');

if (withdrawal.lte(balance)) {
    console.log('可以提现');
} else {
    console.log('余额不足');
}

场景 5:科学计算(幂运算)

// 导入Big.js库
import Big from 'big.js';

// 定义基数
const base = new Big('2');

// 定义指数
const exponent = 64;

// 计算幂运算结果
const result = base.pow(exponent); // 结果将是18446744073709551616

// 输出结果
console.log(result.toString()); // 输出: '18446744073709551616'

场景 6:区块链交易金额校验

// 导入Big.js库
import Big from 'big.js';

// 定义要转账的金额
const transferAmount = new Big('0.000000123456');

// 定义最小转账金额限制
const minTransfer = new Big('0.0000001');

// 检查转账金额是否满足最低要求
if (transferAmount.gte(minTransfer)) {
    console.log('交易有效');
} else {
    console.log('交易金额过低');
}

场景 7:数据统计分析(平均值)

// 导入Big.js库
import Big from 'big.js';

// 定义数字数组
const values = ['12.34', '45.67', '89.01'];

// 使用reduce方法计算数组中所有数字的总和
// 初始值为new Big(0),然后对每个元素使用plus方法进行累加
const sum = values.reduce((acc, val) => acc.plus(val), new Big(0));

// 计算平均值
const avg = sum.div(values.length);

// 输出结果
console.log(`总和:${sum}`);   // 输出: '147.02'
console.log(`平均值:${avg}`); // 输出: '49.00666666666666666666'

六、注意事项与最佳实践

⚠️ 风险点

风险 描述
❌ 不要混用 Big 与原生 Number 运算 new Big(1) + 1 会出错
❌ 不要将对象或函数传入构造函数 必须是数字或字符串
❌ 不要频繁创建 Big 实例 在循环或高频调用中注意性能优化
❌ 不要忘记 .toString().toFixed() 输出 否则返回的是 Big 对象引用

✅ 最佳实践

实践 说明
✅ 总是使用字符串初始化 避免浮点精度问题
✅ 使用 .toFixed(n) 控制输出格式 特别是在 UI 显示时
✅ 使用 .eq(), .lt(), .gt() 替代 ===, <, > 避免类型强制转换错误
✅ 使用 Big.DP 设置默认精度 统一项目中的计算规则
✅ 使用 .round(dp, rm) 控制舍入 提高财务一致性
✅ 封装成工具类 提高复用性和可维护性

七、高级技巧与封装建议

1. 封装成通用计算函数

// 导入Big.js库,用于高精度数学运算
import Big from 'big.js';

/**
 * 执行基本数学运算的函数
 * @param op 运算类型:'add'(加法), 'sub'(减法), 'mul'(乘法), 'div'(除法)
 * @param a 第一个操作数(字符串形式)
 * @param b 第二个操作数(字符串形式)
 * @returns 运算结果,保留两位小数的字符串
 */
function calc(op: 'add' | 'sub' | 'mul' | 'div', a: string, b: string): string {
    // 将字符串参数转换为Big.js对象,以便进行高精度计算
    const x = new Big(a);
    const y = new Big(b);

    // 根据操作符执行相应的数学运算
    switch (op) {
        case 'add': 
            // 执行加法运算,并将结果格式化为保留两位小数的字符串
            return x.plus(y).toFixed(2);
        case 'sub': 
            // 执行减法运算,并将结果格式化为保留两位小数的字符串
            return x.minus(y).toFixed(2);
        case 'mul': 
            // 执行乘法运算,并将结果格式化为保留两位小数的字符串
            return x.times(y).toFixed(2);
        case 'div': 
            // 执行除法运算,并将结果格式化为保留两位小数的字符串
            return x.div(y).toFixed(2);
    }
}

// 测试函数
console.log(calc('add', '10.01', '20.02')); // 输出: '30.03'

2. 与 Vue/React 结合使用(如你的项目)

在 Vue 中,可在 methods或 utils.js 中封装:

// utils.js
import Big from 'big.js';

export function formatMoney(value: string | number): string {
    return new Big(value).toFixed(2);
}
<template>
  <div>总价:{{ formatMoney(total) }}</div>
</template>

<script>
import { formatMoney } from '@/utils';
export default {
  data() {
    return {
      total: '123.456'
    };
  },
  methods: {
    formatMoney
  }
};
</script>

八、常见错误与解决方案

错误 原因 解决方案
NaN 错误 传入非法字符 使用前验证输入
Invalid Big value 构造参数无效 确保是字符串或数字
Uncaught TypeError: Cannot convert instance of Big to primitive 直接使用 + 运算符 改用 .plus() 方法
Exponential notation not supported 输入含 e 科学计数法 先转为标准数字格式

九、总结与面试题

big.js 要点 内容
✅ 主要用途 高精度浮点数运算
✅ 优势 轻量、安全、跨平台
✅ 推荐使用场景 金融、支付、区块链、科学计算
✅ 注意事项 不要混用原生数字,控制精度
✅ 替代方案 decimal.js(更强大但更大)

big.js 面试题精选(10大高频面试题)


1. 为什么在 JavaScript 中需要使用 big.js 进行浮点数运算?

参考答案:

JavaScript 使用 IEEE 754 浮点数标准,导致某些小数运算存在精度丢失问题。例如:

0.1 + 0.2; // 0.30000000000000004 ❌

big.js 提供了高精度的十进制运算能力,避免此类误差,适用于金融、支付等对精度要求极高的场景。

使用 big.js 示例:

new Big(0.1).plus(0.2).toString(); // '0.3' ✅

2. 如何创建一个 Big 对象?有哪些推荐方式?

参考答案:

可以通过以下方式创建:

new Big(123);            // 数字
new Big('123.45');       // 推荐:字符串(避免精度丢失)
new Big(new Big(123));   // Big 实例克隆

推荐方式是字符串初始化,因为直接传入浮点数可能会因 JS 原生解析而引入误差。


3. big.js 支持哪些基本运算方法?请举例说明。

参考答案:

方法 功能 示例
.plus(n) 加法 new Big(0.1).plus(0.2)
.minus(n) 减法 new Big(1.2).minus(0.7)
.times(n) 乘法 new Big(1.2).times(3)
.div(n[, dp]) 除法(可指定小数位) new Big(1).div(3, 2)

示例:

const result = new Big('10').div('3', 2); // '3.33'

4. 如何比较两个 Big 实例的大小?能否用 <>

参考答案:

不能直接使用 <>,应使用如下方法:

a.eq(b);  // 是否相等
a.lt(b);  // a < b
a.gt(b);  // a > b
a.lte(b); // a <= b
a.gte(b); // a >= b

正确写法:

const a = new Big('5');
const b = new Big('3');

console.log(a.gt(b)); // true

5. big.js 如何控制输出的小数位数和舍入方式?

参考答案:

可以使用 .toFixed(dp).round(dp, rm) 控制格式化输出和舍入方式。

const num = new Big('3.14159');

num.toFixed(2);        // '3.14'
num.round(3);          // '3.142'

// 设置全局默认行为
Big.DP = 20;    // 默认保留 20 位小数
Big.RM = 1;     // 舍入模式(0:四舍五入, 1:向下取整, 2:向上取整, 3:去尾法)

6. big.js 的舍入模式有哪些?分别代表什么含义?

参考答案:

Big.RM 支持以下舍入模式(共 4 种):

模式值 含义
0 四舍五入(默认)
1 向下取整(截断)
2 向上取整
3 去尾法(不常用)

示例:

Big.RM = 1;
new Big('3.999').round(0); // '3'

7. big.js 和 decimal.js 有什么区别?你如何选择?

参考答案:

特性 big.js decimal.js
体积 更小(压缩后 < 5KB) 较大
功能 精简实用 更强大(支持指数、三角函数等)
性能 更快 略慢
使用难度 简单易用 配置更复杂
适用场景 金融计算、基础数学 科学计算、复杂业务逻辑

选择建议:

  • 如果只需要加减乘除、比较、格式化,选 big.js
  • 如果需要高级数学运算或更高定制化,选 decimal.js

8. big.js 是否可以用于 Vue/React 等前端框架中?如何封装?

参考答案:

是的,big.js 可以用于任何前端框架中,推荐封装成工具类或自定义 Hook / Filter。

Vue 封装示例:

// utils/bigUtils.ts
import Big from 'big.js';

export function formatMoney(value: string | number): string {
    return new Big(value).toFixed(2);
}
<template>
  <div>价格:{{ formatMoney(price) }}</div>
</template>

<script>
import { formatMoney } from '@/utils/bigUtils';
export default {
  data() {
    return {
      price: '19.99'
    };
  },
  methods: {
    formatMoney
  }
};
</script>

9. big.js 在进行大量循环计算时性能如何?是否需要注意优化?

参考答案:

虽然 big.js 性能较好,但在高频循环或大数据处理中仍需注意:

  • 频繁创建 Big 实例会带来额外开销;
  • 避免在渲染层直接做复杂计算,应在数据处理阶段完成;
  • 可缓存中间结果,减少重复创建;
  • 若性能成为瓶颈,考虑使用 Web Worker 异步处理。

示例优化:

let total = new Big(0);
for (let i = 0; i < items.length; i++) {
    total = total.plus(items[i].price);
}

10. big.js 如何处理非法输入?如何防止运行时错误?

参考答案:

big.js 构造函数若传入非法参数会抛出异常,因此必须进行输入校验:

function safeParse(input) {
    try {
        return new Big(input);
    } catch (e) {
        console.error('无效数值:', input);
        return new Big(0);
    }
}

safeParse('abc'); // 输出 0,并提示错误

推荐做法:

  • 输入前验证类型或格式;
  • 使用 try-catch 包裹构造过程;
  • 对用户输入进行防抖/节流处理;
  • 结合表单验证库(如 Vuelidate)提前拦截非法输入;

✅ 总结

题号 主题
1 JS 浮点数精度问题与 big.js 的作用
2 Big 实例的创建方式与最佳实践
3 常见运算方法及其使用方式
4 比较操作符的替代方法
5 格式化输出与舍入设置
6 big.js 与 decimal.js 的对比
7 框架集成与工具封装
8 性能优化技巧
9 错误处理与输入验证
10 安全构建实例的方法

十、结语

如果你正在开发一个 Vue/React 商业系统,强烈建议你在涉及金额、汇率、折扣、库存等关键业务逻辑中使用 big.js 来保障计算精度和数据准确性。

老曹建议将 big.js 工具函数统一放在 /utils/financial.js 中,并在需要的地方按需引入。

你可能感兴趣的:(前端业务实践,javascript,前端,big.js,学习,教程,金融计算,大数字计算)