big.js快速上手指南(最全最詳細(xì))
一、概念與歷史發(fā)展
1. 概念
big.js
是一個(gè)輕量級(jí)的 JavaScript 庫(kù),用于處理 高精度浮點(diǎn)數(shù)運(yùn)算。它解決了 JavaScript 原生浮點(diǎn)數(shù)精度丟失的問(wèn)題,適用于金融計(jì)算、科學(xué)計(jì)算等對(duì)精度要求極高的場(chǎng)景。
?? JS 浮點(diǎn)數(shù)問(wèn)題示例:
0.1 + 0.2; // 0.30000000000000004 ? 精度錯(cuò)誤
使用 big.js
后:
new Big(0.1).plus(0.2).toString(); // '0.3' ? 精確結(jié)果
2. 歷史發(fā)展
- 2014 年:由 MikeMcl 開(kāi)發(fā)并開(kāi)源,最初名為
BigNumber.js
- 2018 年:更名為
big.js
,成為 GitHub 上最受歡迎的高精度數(shù)字庫(kù)之一 - 特點(diǎn):小巧(壓縮后 < 5KB)、無(wú)依賴(lài)、兼容性好(支持 IE9+)
- 適用領(lǐng)域:電商價(jià)格計(jì)算、銀行利息結(jié)算、區(qū)塊鏈交易、數(shù)據(jù)分析等
二、安裝與引入方式
1. 安裝(Node.js 環(huán)境)
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);
三、基本語(yǔ)法與 API
1. 創(chuàng)建 Big 實(shí)例
new Big(n: number | string | Big): Big
參數(shù)類(lèi)型 | 示例 | 說(shuō)明 |
---|---|---|
數(shù)字 | new Big(123.45) | 推薦使用字符串避免精度丟失 |
字符串 | new Big('123.45') | 最推薦方式,確保精確解析 |
Big 對(duì)象 | new Big(new Big(123)) | 克隆 |
?? 不建議傳入復(fù)雜表達(dá)式或函數(shù),應(yīng)先轉(zhuǎn)換為字符串或數(shù)字。
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]) | 除法(可指定小數(shù)位) | new Big(1).div(3, 2) |
.mod(n) | 取模 | new Big(10).mod(3) |
.pow(exp) | 冪運(yùn)算 | 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() | 轉(zhuǎn)換為原生 Number | new Big(123).toNumber() |
.toString() | 輸出字符串 | new Big(123.456).toString() |
.toFixed(dp) | 格式化固定小數(shù)位 | new Big(3.14159).toFixed(2) |
四、配置項(xiàng)(全局設(shè)置)
你可以通過(guò) Big.DP
和 Big.RM
設(shè)置默認(rèn)行為:
Big.DP = 20; // 默認(rèn)保留 20 位小數(shù) Big.RM = 1; // 舍入模式(0:四舍五入, 1:向下取整, 2:向上取整, 3:去尾法)
五、所有使用場(chǎng)景詳解
場(chǎng)景 1:金融計(jì)算(加減乘除)
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'
場(chǎng)景 2:貨幣匯率換算
// 導(dǎo)入Big.js庫(kù) import Big from 'big.js'; // 定義美元金額 const usd = new Big('100'); // 定義匯率(1美元兌換7.25人民幣) const rate = new Big('7.25'); // USD to CNY // 計(jì)算等值人民幣金額 const cny = usd.times(rate); // 結(jié)果將是'725.00' // 輸出結(jié)果,保留兩位小數(shù) console.log(cny.toFixed(2)); // 輸出: '725.00'
場(chǎng)景 3:商品總價(jià)計(jì)算(帶數(shù)量)
const price = new Big('29.99'); const quantity = 3; const totalPrice = price.times(quantity); // '89.97' console.log(totalPrice.toString());
場(chǎng)景 4:大額資金比較(安全風(fēng)控)
const balance = new Big('1000000.00'); const withdrawal = new Big('999999.99'); if (withdrawal.lte(balance)) { console.log('可以提現(xiàn)'); } else { console.log('余額不足'); }
場(chǎng)景 5:科學(xué)計(jì)算(冪運(yùn)算)
// 導(dǎo)入Big.js庫(kù) import Big from 'big.js'; // 定義基數(shù) const base = new Big('2'); // 定義指數(shù) const exponent = 64; // 計(jì)算冪運(yùn)算結(jié)果 const result = base.pow(exponent); // 結(jié)果將是18446744073709551616 // 輸出結(jié)果 console.log(result.toString()); // 輸出: '18446744073709551616'
場(chǎng)景 6:區(qū)塊鏈交易金額校驗(yàn)
// 導(dǎo)入Big.js庫(kù) import Big from 'big.js'; // 定義要轉(zhuǎn)賬的金額 const transferAmount = new Big('0.000000123456'); // 定義最小轉(zhuǎn)賬金額限制 const minTransfer = new Big('0.0000001'); // 檢查轉(zhuǎn)賬金額是否滿(mǎn)足最低要求 if (transferAmount.gte(minTransfer)) { console.log('交易有效'); } else { console.log('交易金額過(guò)低'); }
場(chǎng)景 7:數(shù)據(jù)統(tǒng)計(jì)分析(平均值)
// 導(dǎo)入Big.js庫(kù) import Big from 'big.js'; // 定義數(shù)字?jǐn)?shù)組 const values = ['12.34', '45.67', '89.01']; // 使用reduce方法計(jì)算數(shù)組中所有數(shù)字的總和 // 初始值為new Big(0),然后對(duì)每個(gè)元素使用plus方法進(jìn)行累加 const sum = values.reduce((acc, val) => acc.plus(val), new Big(0)); // 計(jì)算平均值 const avg = sum.div(values.length); // 輸出結(jié)果 console.log(`總和:${sum}`); // 輸出: '147.02' console.log(`平均值:${avg}`); // 輸出: '49.00666666666666666666'
六、注意事項(xiàng)與最佳實(shí)踐
?? 風(fēng)險(xiǎn)點(diǎn)
風(fēng)險(xiǎn) | 描述 |
---|---|
? 不要混用 Big 與原生 Number 運(yùn)算 | 如 new Big(1) + 1 會(huì)出錯(cuò) |
? 不要將對(duì)象或函數(shù)傳入構(gòu)造函數(shù) | 必須是數(shù)字或字符串 |
? 不要頻繁創(chuàng)建 Big 實(shí)例 | 在循環(huán)或高頻調(diào)用中注意性能優(yōu)化 |
? 不要忘記 .toString() 或 .toFixed() 輸出 | 否則返回的是 Big 對(duì)象引用 |
? 最佳實(shí)踐
實(shí)踐 | 說(shuō)明 |
---|---|
? 總是使用字符串初始化 | 避免浮點(diǎn)精度問(wèn)題 |
? 使用 .toFixed(n) 控制輸出格式 | 特別是在 UI 顯示時(shí) |
? 使用 .eq() , .lt() , .gt() 替代 === , < , > | 避免類(lèi)型強(qiáng)制轉(zhuǎn)換錯(cuò)誤 |
? 使用 Big.DP 設(shè)置默認(rèn)精度 | 統(tǒng)一項(xiàng)目中的計(jì)算規(guī)則 |
? 使用 .round(dp, rm) 控制舍入 | 提高財(cái)務(wù)一致性 |
? 封裝成工具類(lèi) | 提高復(fù)用性和可維護(hù)性 |
七、高級(jí)技巧與封裝建議
1. 封裝成通用計(jì)算函數(shù)
// 導(dǎo)入Big.js庫(kù),用于高精度數(shù)學(xué)運(yùn)算 import Big from 'big.js'; /** * 執(zhí)行基本數(shù)學(xué)運(yùn)算的函數(shù) * @param op 運(yùn)算類(lèi)型:'add'(加法), 'sub'(減法), 'mul'(乘法), 'div'(除法) * @param a 第一個(gè)操作數(shù)(字符串形式) * @param b 第二個(gè)操作數(shù)(字符串形式) * @returns 運(yùn)算結(jié)果,保留兩位小數(shù)的字符串 */ function calc(op: 'add' | 'sub' | 'mul' | 'div', a: string, b: string): string { // 將字符串參數(shù)轉(zhuǎn)換為Big.js對(duì)象,以便進(jìn)行高精度計(jì)算 const x = new Big(a); const y = new Big(b); // 根據(jù)操作符執(zhí)行相應(yīng)的數(shù)學(xué)運(yùn)算 switch (op) { case 'add': // 執(zhí)行加法運(yùn)算,并將結(jié)果格式化為保留兩位小數(shù)的字符串 return x.plus(y).toFixed(2); case 'sub': // 執(zhí)行減法運(yùn)算,并將結(jié)果格式化為保留兩位小數(shù)的字符串 return x.minus(y).toFixed(2); case 'mul': // 執(zhí)行乘法運(yùn)算,并將結(jié)果格式化為保留兩位小數(shù)的字符串 return x.times(y).toFixed(2); case 'div': // 執(zhí)行除法運(yùn)算,并將結(jié)果格式化為保留兩位小數(shù)的字符串 return x.div(y).toFixed(2); } } // 測(cè)試函數(shù) console.log(calc('add', '10.01', '20.02')); // 輸出: '30.03'
2. 與 Vue/React 結(jié)合使用(如你的項(xiàng)目)
在 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>總價(jià):{{ formatMoney(total) }}</div> </template> <script> import { formatMoney } from '@/utils'; export default { data() { return { total: '123.456' }; }, methods: { formatMoney } }; </script>
八、常見(jiàn)錯(cuò)誤與解決方案
錯(cuò)誤 | 原因 | 解決方案 |
---|---|---|
NaN 錯(cuò)誤 | 傳入非法字符 | 使用前驗(yàn)證輸入 |
Invalid Big value | 構(gòu)造參數(shù)無(wú)效 | 確保是字符串或數(shù)字 |
Uncaught TypeError: Cannot convert instance of Big to primitive | 直接使用 + 運(yùn)算符 | 改用 .plus() 方法 |
Exponential notation not supported | 輸入含 e 科學(xué)計(jì)數(shù)法 | 先轉(zhuǎn)為標(biāo)準(zhǔn)數(shù)字格式 |
九、總結(jié)與面試題
big.js 要點(diǎn) | 內(nèi)容 |
---|---|
? 主要用途 | 高精度浮點(diǎn)數(shù)運(yùn)算 |
? 優(yōu)勢(shì) | 輕量、安全、跨平臺(tái) |
? 推薦使用場(chǎng)景 | 金融、支付、區(qū)塊鏈、科學(xué)計(jì)算 |
? 注意事項(xiàng) | 不要混用原生數(shù)字,控制精度 |
? 替代方案 | decimal.js(更強(qiáng)大但更大) |
big.js面試題精選(10大高頻面試題)
1.為什么在 JavaScript 中需要使用 big.js 進(jìn)行浮點(diǎn)數(shù)運(yùn)算?
參考答案:
JavaScript 使用 IEEE 754 浮點(diǎn)數(shù)標(biāo)準(zhǔn),導(dǎo)致某些小數(shù)運(yùn)算存在精度丟失問(wèn)題。例如:
0.1 + 0.2; // 0.30000000000000004 ?
big.js
提供了高精度的十進(jìn)制運(yùn)算能力,避免此類(lèi)誤差,適用于金融、支付等對(duì)精度要求極高的場(chǎng)景。
使用 big.js
示例:
new Big(0.1).plus(0.2).toString(); // '0.3' ?
2.如何創(chuàng)建一個(gè) Big 對(duì)象?有哪些推薦方式?
參考答案:
可以通過(guò)以下方式創(chuàng)建:
new Big(123); // 數(shù)字 new Big('123.45'); // 推薦:字符串(避免精度丟失) new Big(new Big(123)); // Big 實(shí)例克隆
推薦方式是字符串初始化,因?yàn)橹苯觽魅敫↑c(diǎn)數(shù)可能會(huì)因 JS 原生解析而引入誤差。
3.big.js 支持哪些基本運(yùn)算方法?請(qǐng)舉例說(shuō)明。
參考答案:
方法 | 功能 | 示例 |
---|---|---|
.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]) | 除法(可指定小數(shù)位) | new Big(1).div(3, 2) |
示例:
const result = new Big('10').div('3', 2); // '3.33'
4.如何比較兩個(gè) Big 實(shí)例的大???能否用<或>?
參考答案:
不能直接使用 <
或 >
,應(yīng)使用如下方法:
a.eq(b); // 是否相等 a.lt(b); // a < b a.gt(b); // a > b a.lte(b); // a <= b a.gte(b); // a >= b
正確寫(xiě)法:
const a = new Big('5'); const b = new Big('3'); console.log(a.gt(b)); // true
5.big.js 如何控制輸出的小數(shù)位數(shù)和舍入方式?
參考答案:
可以使用 .toFixed(dp)
和 .round(dp, rm)
控制格式化輸出和舍入方式。
const num = new Big('3.14159'); num.toFixed(2); // '3.14' num.round(3); // '3.142' // 設(shè)置全局默認(rèn)行為 Big.DP = 20; // 默認(rèn)保留 20 位小數(shù) Big.RM = 1; // 舍入模式(0:四舍五入, 1:向下取整, 2:向上取整, 3:去尾法)
6.big.js 的舍入模式有哪些?分別代表什么含義?
參考答案:
Big.RM
支持以下舍入模式(共 4 種):
模式值 | 含義 |
---|---|
0 | 四舍五入(默認(rèn)) |
1 | 向下取整(截?cái)啵?/td> |
2 | 向上取整 |
3 | 去尾法(不常用) |
示例:
Big.RM = 1; new Big('3.999').round(0); // '3'
7.big.js 和 decimal.js 有什么區(qū)別?你如何選擇?
參考答案:
特性 | big.js | decimal.js |
---|---|---|
體積 | 更?。▔嚎s后 < 5KB) | 較大 |
功能 | 精簡(jiǎn)實(shí)用 | 更強(qiáng)大(支持指數(shù)、三角函數(shù)等) |
性能 | 更快 | 略慢 |
使用難度 | 簡(jiǎn)單易用 | 配置更復(fù)雜 |
適用場(chǎng)景 | 金融計(jì)算、基礎(chǔ)數(shù)學(xué) | 科學(xué)計(jì)算、復(fù)雜業(yè)務(wù)邏輯 |
選擇建議:
- 如果只需要加減乘除、比較、格式化,選
big.js
- 如果需要高級(jí)數(shù)學(xué)運(yùn)算或更高定制化,選
decimal.js
8.big.js 是否可以用于 Vue/React 等前端框架中?如何封裝?
參考答案:
是的,big.js
可以用于任何前端框架中,推薦封裝成工具類(lèi)或自定義 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>價(jià)格:{{ formatMoney(price) }}</div> </template> <script> import { formatMoney } from '@/utils/bigUtils'; export default { data() { return { price: '19.99' }; }, methods: { formatMoney } }; </script>
9.big.js 在進(jìn)行大量循環(huán)計(jì)算時(shí)性能如何?是否需要注意優(yōu)化?
參考答案:
雖然 big.js
性能較好,但在高頻循環(huán)或大數(shù)據(jù)處理中仍需注意:
- 頻繁創(chuàng)建 Big 實(shí)例會(huì)帶來(lái)額外開(kāi)銷(xiāo);
- 避免在渲染層直接做復(fù)雜計(jì)算,應(yīng)在數(shù)據(jù)處理階段完成;
- 可緩存中間結(jié)果,減少重復(fù)創(chuàng)建;
- 若性能成為瓶頸,考慮使用 Web Worker 異步處理。
示例優(yōu)化:
let total = new Big(0); for (let i = 0; i < items.length; i++) { total = total.plus(items[i].price); }
10.big.js 如何處理非法輸入?如何防止運(yùn)行時(shí)錯(cuò)誤?
參考答案:
big.js
構(gòu)造函數(shù)若傳入非法參數(shù)會(huì)拋出異常,因此必須進(jìn)行輸入校驗(yàn):
function safeParse(input) { try { return new Big(input); } catch (e) { console.error('無(wú)效數(shù)值:', input); return new Big(0); } } safeParse('abc'); // 輸出 0,并提示錯(cuò)誤
推薦做法:
- 輸入前驗(yàn)證類(lèi)型或格式;
- 使用 try-catch 包裹構(gòu)造過(guò)程;
- 對(duì)用戶(hù)輸入進(jìn)行防抖/節(jié)流處理;
- 結(jié)合表單驗(yàn)證庫(kù)(如 Vuelidate)提前攔截非法輸入;
總結(jié)
題號(hào) | 主題 |
---|---|
1 | JS 浮點(diǎn)數(shù)精度問(wèn)題與 big.js 的作用 |
2 | Big 實(shí)例的創(chuàng)建方式與最佳實(shí)踐 |
3 | 常見(jiàn)運(yùn)算方法及其使用方式 |
4 | 比較操作符的替代方法 |
5 | 格式化輸出與舍入設(shè)置 |
6 | big.js 與 decimal.js 的對(duì)比 |
7 | 框架集成與工具封裝 |
8 | 性能優(yōu)化技巧 |
9 | 錯(cuò)誤處理與輸入驗(yàn)證 |
10 | 安全構(gòu)建實(shí)例的方法 |
十、結(jié)語(yǔ)
如果你正在開(kāi)發(fā)一個(gè) Vue/React 商業(yè)系統(tǒng),強(qiáng)烈建議你在涉及金額、匯率、折扣、庫(kù)存等關(guān)鍵業(yè)務(wù)邏輯中使用 big.js
來(lái)保障計(jì)算精度和數(shù)據(jù)準(zhǔn)確性。
老曹建議將 big.js
工具函數(shù)統(tǒng)一放在 /utils/financial.js
中,并在需要的地方按需引入。
到此這篇關(guān)于big.js快速上手的文章就介紹到這了,更多相關(guān)big.js上手指南內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript 完美運(yùn)動(dòng)框架(逐行分析代碼,讓你輕松了運(yùn)動(dòng)的原理)
這篇文章主要介紹了Javascript 完美運(yùn)動(dòng)框架,逐行分析代碼,讓你輕松了運(yùn)動(dòng)的原理,需要的朋友可以參考下2015-01-01微信小程序?qū)崿F(xiàn)地區(qū)選擇偽五級(jí)聯(lián)動(dòng)
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)地區(qū)選擇偽五級(jí)聯(lián)動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07es6函數(shù)name屬性功能與用法實(shí)例分析
這篇文章主要介紹了es6函數(shù)name屬性,結(jié)合實(shí)例形式分析了es6函數(shù)name屬性基本原理、功能、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04JS頁(yè)面獲取 session 值,作用域和閉包學(xué)習(xí)筆記
這篇文章主要介紹了JS頁(yè)面獲取 session 值,作用域和閉包,結(jié)合具體實(shí)例形式分析了javascript與jsp交互獲取session值、函數(shù)作用域及閉包相關(guān)操作技巧,需要的朋友可以參考下2019-10-10動(dòng)態(tài)創(chuàng)建按鈕的JavaScript代碼
本文給大家分享一段JS實(shí)例代碼介紹動(dòng)態(tài)創(chuàng)建按鈕的方法,需要的朋友參考下本文2016-01-01