在工作中,遇到一個問題,明明后端接口返回的id是16437976441985843999(只是舉例),但是用這個id去查詢詳情接口時總是報錯,后端開發人員查了日志是傳的id不對,實際是16437976441985843000,瀏覽器接口返回的id和后端原本給的id竟然不一致,查了相關文檔:
在Long長度大於17位時,就會出現精度丟失的問題
簡單解釋就是:JS自身Number類型的設計原因,原生JS不完全支持long
根本原因:
計算機的二進制實現和位數限制有些數無法有限表示。就像一些無理數不能有限表示,如 圓周率 3.1415926…,1.3333… 等。JS 遵循 IEEE 754 規范,采用雙精度存儲(double precision),占用 64 bit,如圖:

其中:1位用來表示符號位;11位用來表示指數;52位表示尾數
浮點數,比如

此時只能模仿十進制進行四舍五入了,但是二進制只有 0 和 1 兩個,於是變為 0 舍 1 入。這即是計算機中部分浮點數運算時出現誤差,丟失精度的根本原因。
大整數的精度丟失和浮點數本質上是一樣的,尾數位最大是 52 位,因此 JS 中能精准表示的最大整數是 Math.pow(2, 53),十進制即 9007199254740992。大於 9007199254740992 的可能會丟失精度
看似有窮的數字, 在計算機的二進制表示里卻是無窮的,由於存儲位數限制因此存在“舍去”,精度丟失就發生了。
對於前后台傳參Long類型而言,JS內置有32位整數,而number類型的安全整數是53位。如果超過53位,則精度會丟失。如果后台傳來一個64位的Long型整數,因為超過了53位,所以后台返回的值和前台獲取的值會不一樣。下面看一下如何處理這種精度丟失問題。
(以上對於根本原因的解釋:原文鏈接:https://blog.csdn.net/u010028869/java/article/details/86563382)
解決辦法:
1. 最直接的后端人員可把long型值轉成String類型給前端,這里主要介紹前端解決方案
2. 端實現一個json parser
1> 第一步,安裝 -- jison
npm install jison
2> 第二步,新增兩個文件,並修改其中一個文件關於Number類型轉換的邏輯
在github https://github.com/zaach/jsonlint/tree/master/src 這個鏈接下載 jsonlint.l 、jinsonlint.y 放在本地文件夾下,在此以公司的vue項目為例,放在static目錄下:,如圖

這兩個文件分別是 詞表文件 - lexfile - jsonlint.l、語法文件 - grammFile - jsonlint.y
修改 jsonlint.y 詞法文件關於JSONNumber的這段代碼:
源代碼這樣:

修改后:
3> 第三步,生成我們要的 jsonlint.js
用第一步jison把第二步的兩位文件合成一個我們要的最終插件,在控制台輸入:

4> 第四步,引入jsonlint.js文件,以便使用

5> 第五步,在我們自己axios封裝的request.js中使用:

最后,我們就可以在接口里看到精確的Long型值了。
(參考自:https://blog.csdn.net/fifteen718/article/details/82783246?utm_source=blogxgwz9)
