LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

JS 處理長整型數(shù)字的坑:從雪花 ID 精度丟失說起

freeflydom
2025年7月10日 9:46 本文熱度 640

在服務(wù)端使用 64 位長整型(Int64)數(shù)字,而前端通過 JavaScript 的number類型接收時(shí),若數(shù)值超過2^53 - 1(即 9007199254740991),會(huì)出現(xiàn)數(shù)值不相等的問題。這一現(xiàn)象的核心原因是 JavaScript 中number類型的精度限制,而雪花算法生成的 ID(通常為 64 位)恰好屬于這類場景,因此需要特別處理。

一、問題根源:JavaScript 中number的精度限制

JavaScript 的number類型基于IEEE 754 雙精度浮點(diǎn)數(shù)標(biāo)準(zhǔn)實(shí)現(xiàn),其底層存儲(chǔ)結(jié)構(gòu)決定了它的精度范圍:

  • 雙精度浮點(diǎn)數(shù)的 “尾數(shù)(mantissa)” 部分占 52 位,加上隱藏的 1 位 “整數(shù)位”,總共可表示53 位有效精度。

  • 這意味著:對(duì)于整數(shù),number類型能精確表示的范圍是[-2^53 + 1, 2^53 - 1],這個(gè)范圍外的整數(shù)無法被精確存儲(chǔ),會(huì)出現(xiàn) “精度丟失”。

當(dāng)服務(wù)端返回的 Int64 數(shù)值超過2^53 - 1時(shí),JavaScript 的number會(huì)因無法精確表示該值,導(dǎo)致存儲(chǔ)的結(jié)果與實(shí)際值不一致(例如末尾幾位被截?cái)嗷蛩纳嵛迦耄?/p>

二、典型場景:雪花算法 ID 的問題

雪花算法(Snowflake)生成的 ID 是 64 位整數(shù),結(jié)構(gòu)通常為:

  • 1 位符號(hào)位(固定為 0,保證正數(shù));

  • 41 位時(shí)間戳;

  • 10 位機(jī)器 ID;

  • 12 位序列號(hào)。

顯然,64 位整數(shù)的最大值為2^63 - 1(約 9e18),遠(yuǎn)超過2^53 - 1,因此用number接收時(shí)必然會(huì)丟失精度,導(dǎo)致前端存儲(chǔ)的 ID 與服務(wù)端實(shí)際值不匹配(例如服務(wù)端 ID 為1234567890123456789,前端接收后可能變成1234567890123456700)。

三、解決方法:如何避免精度丟失?

解決的核心思路是繞開 JavaScriptnumber類型的精度限制,常見方案如下:

1. 以字符串形式傳遞大整數(shù)

最直接的方式是服務(wù)端在返回?cái)?shù)據(jù)時(shí),將 Int64 類型的字段轉(zhuǎn)換為字符串,前端接收后以字符串形式存儲(chǔ)和使用。

  • 服務(wù)端處理:例如在 Java 中,將Long類型的雪花 ID 轉(zhuǎn)換為String后再序列化到 JSON 中;
  • 前端接收:直接使用字符串類型的 ID(無需轉(zhuǎn)換為number),避免精度丟失。

2. 前端使用BigInt類型處理大整數(shù)

BigInt是 JavaScript 中專門用于表示任意精度整數(shù)的類型,可精確存儲(chǔ)超過2^53 - 1的數(shù)值。

  • 服務(wù)端:保持 Int64 類型的數(shù)值(例如 JSON 中直接存儲(chǔ)數(shù)字);
  • 前端處理:
    • 接收時(shí),通過BigInt()構(gòu)造函數(shù)將數(shù)值轉(zhuǎn)換為BigInt類型(例如const id = BigInt(response.id));

    • 注意:BigIntnumber不能直接運(yùn)算,需顯式轉(zhuǎn)換(例如BigInt(123) + 456n,其中nBigInt的字面量后綴)。

示例
服務(wù)端返回 JSON:{ "id": 1234567890123456789 }
前端處理:

javascript

// 直接用number接收會(huì)丟失精度
const numId = response.id; // 結(jié)果可能為1234567890123456700(錯(cuò)誤)
// 用BigInt接收可保持精度
const bigIntId = BigInt(response.id); // 結(jié)果為1234567890123456789n(正確)

3. 框架 / 序列化工具的配置優(yōu)化

在前后端數(shù)據(jù)交互中(尤其是 JSON 序列化 / 反序列化),可通過工具配置自動(dòng)處理大整數(shù):

  • 例如,使用JSON.parse時(shí),通過reviver函數(shù)將大整數(shù)轉(zhuǎn)換為BigInt

    javascript

    const data = JSON.parse(response, (key, value) => {
      // 假設(shè)ID字段名為"id",且數(shù)值超過2^53-1
      if (key === 'id' && typeof value === 'number' && value > 2**53 - 1) {
        return BigInt(value);
      }
      return value;
    });
    
  • 部分框架(如 Vue、React)或 HTTP 客戶端(如 Axios)可配置攔截器,自動(dòng)將大整數(shù)字段轉(zhuǎn)換為BigInt或字符串。

四、注意事項(xiàng)

  1. 兼容性BigInt在 IE 瀏覽器中不支持,但現(xiàn)代瀏覽器(Chrome、Firefox、Edge 等)均已支持;
  2. 字符串傳遞的優(yōu)勢:若前端僅需展示或傳遞 ID(無需數(shù)值運(yùn)算),字符串形式更簡單,避免BigInt的類型轉(zhuǎn)換成本;
  3. 數(shù)據(jù)庫交互:若前端需將 ID 回傳到服務(wù)端或存儲(chǔ)到數(shù)據(jù)庫,保持字符串或BigInt類型即可(服務(wù)端可再轉(zhuǎn)換為 Int64 處理)。

總結(jié)

當(dāng)服務(wù)端的 Int64 數(shù)值超過2^53 - 1時(shí),JavaScript 的number類型無法精確表示,導(dǎo)致數(shù)值不匹配。解決核心是避開number的精度限制,推薦通過 “字符串傳遞” 或 “前端BigInt處理” 兩種方式,尤其在雪花算法 ID 等 64 位整數(shù)場景中必須使用。

?轉(zhuǎn)自https://juejin.cn/post/7524645466745815059


該文章在 2025/7/10 9:46:53 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲(chǔ)管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

黄频国产免费高清视频,久久不卡精品中文字幕一区,激情五月天AV电影在线观看,欧美国产韩国日本一区二区
丝袜足j国产在线视频456 | 日本一本久a久久精品综合 亚洲一级人成字幕 | 日韩一区二区三区精品视频 | 精品一区二区三区亚洲欧洲 | 欧美成a高清在线观看 | 中文字幕免费伦费影视在线观看 |