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/big.js@6.2.1/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.DP 和 Big.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 中,并在需要的地方按需引入。
到此这篇关于big.js快速上手的文章就介绍到这了,更多相关big.js上手指南内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
