最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript中的精度丟失與分?jǐn)偛黄絾栴}原因及解決方案

 更新時(shí)間:2026年03月12日 10:04:36   作者:yingjuxia.com  
這篇文章主要介紹了JavaScript中浮點(diǎn)數(shù)精度問題,包括根本原因、常見場景及解決方案,推薦使用整數(shù)運(yùn)算、BigInt或高精度庫(如decimal.js)來解決金額計(jì)算的精度問題,需要的朋友可以參考下

大家好!這是很多前端(尤其是金融、電商、支付、報(bào)表)開發(fā)者最頭疼的問題:

console.log(0.1 + 0.2);           // 0.30000000000000004
console.log(0.3 - 0.2);           // 0.09999999999999998
console.log(19.9 * 100);          // 1989.9999999999998
console.log(1.005.toFixed(2));    // "1.00" 而不是 "1.01"

更可怕的是分?jǐn)偛黄剑ń痤~拆分時(shí)總和對(duì)不上):

假設(shè) 100 元分給 3 個(gè)人,每人應(yīng)得 33.333… 元
toFixed(2) 后:33.33 + 33.33 + 33.33 = 99.99(差1分!)

今天這篇保姆級(jí)+生產(chǎn)級(jí)文章,一次性徹底講透原因 + 所有解決方案(從簡單到企業(yè)級(jí)),看完你再也不會(huì)被精度坑了。

1. 根本原因:IEEE 754 雙精度浮點(diǎn)數(shù)(必懂!)

JavaScript 的 Number 類型底層是 64位 IEEE 754 雙精度浮點(diǎn)數(shù)

  • 1位符號(hào) + 11位指數(shù) + 52位尾數(shù)(有效精度約15-16位十進(jìn)制)
  • 二進(jìn)制無法精確表示大部分十進(jìn)制小數(shù)(就像十進(jìn)制無法精確表示1/3)

經(jīng)典二進(jìn)制轉(zhuǎn)換演示(0.1 的二進(jìn)制是無限循環(huán)):

大整數(shù)精度丟失(超過 Number.MAX_SAFE_INTEGER = 9007199254740991):

console.log(9007199254740992 === 9007199254740993); // true!已丟失

2. 常見場景 & 問題匯總

場景典型表現(xiàn)后果
加減乘除小數(shù)0.1+0.2、0.3-0.2顯示多位小數(shù)或不相等
toFixed()1.005.toFixed(2) → “1.00”銀行級(jí)四舍五入錯(cuò)誤
大ID(雪花算法)JSON.parse后后幾位變0ID重復(fù)、數(shù)據(jù)錯(cuò)亂
金額分?jǐn)?/td>100 / 3 = 33.333… → toFixed后總和少1分分?jǐn)偛黄?/strong>(最致命)
循環(huán)累加0.1 加 10 次 ≠ 1報(bào)表總計(jì)對(duì)不上

3. 解決方案對(duì)比(2026推薦排序)

方案1:最簡單——轉(zhuǎn)為整數(shù)計(jì)算(推薦日常金額)

轉(zhuǎn)為(或更小單位),全部用整數(shù)運(yùn)算,最后再除。

// 金額用分存儲(chǔ)
const price = 1999;  // 19.99元
const qty = 3;
const total = price * qty;           // 5997 分
console.log((total / 100).toFixed(2)); // "59.97" 完美

分?jǐn)偛黄浇K極解決(銀行家舍入 + 尾差調(diào)整):

function distribute(amount, parts) {
  const base = Math.floor(amount / parts);
  const remainder = amount % parts;
  const result = new Array(parts).fill(base);
  for (let i = 0; i < remainder; i++) result[i]++;
  return result.map(v => v / 100);  // 轉(zhuǎn)回元
}

distribute(10000, 3); // [3334, 3333, 3333] 分 → 總和正好100.00元

方案2:原生 BigInt(整數(shù)超大數(shù)專用,2026最推薦)

const a = 9007199254740992n;
const b = 1n;
console.log(a + b); // 9007199254740993n  精確!

金額場景(推薦結(jié)合方案1):

const priceInFen = 1999n;
const total = priceInFen * 3n; // 5997n
console.log(Number(total) / 100); // 59.97

方案3:高精度庫(金融/科學(xué)計(jì)算必備)

2026年主流庫對(duì)比(生產(chǎn)驗(yàn)證):

推薦優(yōu)先級(jí)

  1. decimal.js(最推薦)—— 任意精度、API最友好
  2. bignumber.js —— 輕量、速度快
  3. big.js —— 極簡
  4. Dinero.js / currency.js —— 專門做貨幣

decimal.js 實(shí)戰(zhàn)代碼(復(fù)制即用):

import Decimal from 'decimal.js';
Decimal.set({ precision: 20, rounding: Decimal.ROUND_HALF_EVEN });
const a = new Decimal('0.1');
const b = new Decimal('0.2');
console.log(a.plus(b).toString());        // "0.3" 完美
const total = new Decimal('100');
const perPerson = total.dividedBy(3).toFixed(2); // "33.33"
console.log(perPerson); // 不會(huì)分?jǐn)偛黄?/pre>

toFixed 增強(qiáng)版(解決1.005問題):

function accurateToFixed(num, digits = 2) {
  return new Decimal(num).toFixed(digits);
}
accurateToFixed(1.005); // "1.01"

方案4:其他輔助技巧

  • JSON大數(shù):用 json-bigintBigInt 序列化
  • 比較時(shí)用 Number.EPSILONMath.abs(a - b) < Number.EPSILON
  • 顯示時(shí)永遠(yuǎn)用 .toFixed(2) + 庫

4. 生產(chǎn)最佳實(shí)踐(強(qiáng)烈建議)

  1. 所有金額后端存“分”或字符串,前端用 Decimal 或整數(shù)
  2. 前端計(jì)算全部走庫,絕不用原生 + - * /
  3. 分?jǐn)倛鼍?/strong>必須用整數(shù)分?jǐn)?+ 尾差調(diào)整算法
  4. 大ID一律用 BigInt 或字符串
  5. 測試:寫單元測試覆蓋 0.1+0.2、1.005.toFixed、100/3

5. 小結(jié) & 推薦工具

一句話記住

永遠(yuǎn)不要相信 JS 原生 Number 做精確計(jì)算,尤其是錢!

立即行動(dòng)

  • 金額類項(xiàng)目 → 安裝 decimal.js + 改成整數(shù)分存儲(chǔ)
  • 大數(shù)ID → 用 BigIntjson-bigint
  • 快速修復(fù) → 先用 toFixed(2) + Number.EPSILON 兜底

以上就是JavaScript中的精度丟失與分?jǐn)偛黄絾栴}原因及解決方案的詳細(xì)內(nèi)容,更多關(guān)于JavaScript精度丟失與分?jǐn)偛黄降馁Y料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

黔西县| 区。| 库伦旗| 蒙阴县| 广丰县| 崇阳县| 崇阳县| 阳曲县| 炎陵县| 沭阳县| 得荣县| 襄垣县| 慈利县| 清涧县| 淮南市| 临泽县| 盘山县| 武隆县| 舟曲县| 尉氏县| 威宁| 家居| 永昌县| 无极县| 永吉县| 博野县| 客服| 图木舒克市| 榆林市| 贡山| 德格县| 莒南县| 瑞安市| 阿勒泰市| 大洼县| 沧源| 岳阳市| 密山市| 海兴县| 灵川县| 金乡县|