摘要:大數值的精度問題能夠被安全呈現的最大整數是,即。我們可以將需要比較的兩個值進行相減,再與這個機器精度進行比較,如果在誤差范圍內,我們也視為兩個值是相等的。
jquery[.data()]方法近期在項目中有出現大數值的訂單號9148368244236619在調用接口時自動變成9148368244236620的情況,導致請求失誤。本文特意總結了出現這種情況的原因,以及js精度相關的情況。
在本次案例中,訂單號是后端同步渲染到頁面上的,
呈現在頁面上的訂單號數值沒有問題9148368244236619 ,前端此時想獲取到這個訂單號:
var orderNumber = $(".j_OrderNumber).data("ordernumber"); // 9148368244236620 typeof(orderNumber) === "number" // true
在這個取值賦值的過程中,超過安全值的大數值發生了變化,從9148368244236619 變成了91483682442366120 ,這里的問題主要出現在jquery的data方法。
超過安全值Math.pow(2, 53)-1 -- 9007199254740991 的number類型在賦值的過程中會發生精度丟失,而我們在使用jquery的data方法取得的自定義html屬性data-ordernumber值會強制轉換成number類型,導致精度丟失。
而使用js原生的方法取dom節點的屬性時,獲取到的值都是string類型,這樣就不會出現number類型精度丟失的問題。
var orderNumber = $(".j_OrderNumber")[0].dataset.ordernumber // "9148368244236619" typeof(orderNumber) === "string" // true
所以我們在通過自定義屬性取值number類型時,并且預期這些值會是類似訂單號這種會超過安全閾值的數值時,不要使用jquery的data方法。
大數值的精度問題能夠被“安全”呈現的最大整數是Math.pow(2, 53) - 1,即9007199254740992 。在ES6中被定義為Number.MAX_SAFE_INTEGER。
在開發環境,根據程序的特殊性,在有可能出現這種情況時我們應該杜絕掉超出安全閾值的大整數,并給出友好提示:
function isSafeInteger(num) { return typeof(num) === "number" && num % 1 == 0 && Math.abs(num) <= Math.pow(2, 53) -1; }
在一般電商業務中比較常見出現大數值的場景也就是訂單號了,這類場景后端傳值給我們的時候都強制包裝成string類型就會解決大多數的精度丟失問題了。
至于為什么會只有2的53次方-1的整數是安全的,可以看阮神的關于數值的文章有詳細介紹
小數的精度問題小數比較經典的 0.1 + 0.2 === 0.3 // false 問題
0.1 + 0.2 === 0.30000000000000004
對于這類數值比較問題,如果我們已經知道了目標比較值,即如果我們已經明確要與0.3進行比較,我們也可以不需要得到0.1+0.2的真實期望結果值(0.3),因為如果我們要得到0.3,還需要對0.1和0.2進行操作。常規解法:
(0.1 * 10 + 0.2 * 10) / 10 = 0.3
在「你不知道的javascript」一書中有提到一種判斷方法,設置一個誤差范圍值,通常也稱為“機器精度”,對于javascript來說,這個值通常為Math.pow(2, -53)。
我們可以將需要比較的兩個值進行相減,再與這個機器精度進行比較,如果在誤差范圍內,我們也視為兩個值是相等的。
function numbersCloseEnoughToEqual(num1, num2) { return Math.abs(num1 - num2) < Math.pow(2, -53); }小數展示
對于電商業務來講,小數經過四則運算后可能會出現失去精度的問題,但是作為展示來說我們都會調用toFixed()進行小數后幾位的約定,調用了這個方法后小數失去精度的問題也就迎刃而解了,不可能出現0.30000000000000004 這樣的數值。
所以在業務中有需要進行小數四則運算并會展示在頁面中,調用toFixed()方法!
但是toFixed()也有失去精度的時候!
1.335.toFixed(2) // "1.33"
解決辦法
function toFixed(num, s) { var times = Math.pow(10, s) var des = num * times + 0.5 des = parseInt(des, 10) / times return des + "" }小數的四則運算
參考
本文來自二口南洋,有什么需要討論的歡迎找我。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88172.html
摘要:前言在數據敏感的業務場景中,常常會碰到數據精度問題,尤其在金額顯示占比統計等地方,該問題尤為顯著。計算機原理真香數值的精度問題,其實是非?;A的計算機原理知識。前言 在數據敏感的業務場景中,常常會碰到數據精度問題,尤其在金額顯示、占比統計等地方,該問題尤為顯著。由于數據的每一位有效數字都包含真實的業務語義,一點點偏差甚至可能影響業務決策,這讓問題的嚴重性上升了幾個階梯。 那,什么是精度丟失...
摘要:方法使用定點表示法來格式化一個數,會對結果進行四舍五入。該數值在必要時進行四舍五入,另外在必要時會用來填充小數部分,以便小數部分有指定的位數。如果數值大于,該方法會簡單調用并返回一個指數記數法格式的字符串。在環境中,只能是之間,測試版本為。 showImg(https://segmentfault.com/img/remote/1460000011913134?w=768&h=521)...
摘要:基礎極值采用標準的位雙精度格式存儲數值。如果數值的精度超過此限度,第位及后面的會被丟棄。數值的極值分為兩種可表示的極值和可精確計算的極值浮點型不算。超過精度的數值可正確顯示,但由其計算得出的結果可能不準確。整型數值安全區間。 ES6為數值增加了些常量和方法,使計算更為簡便安全。本篇概括了這中的精華知識。 1 基礎 1.1 極值 JS采用IEEE 754標準的64位雙精度格式存儲數值。 ...
摘要:我們可以利用該函數限定返回數值的位數,從而達到提高精度的效果。 一、問題的引入 今天在看基礎js文章的時候發現了一個浮點數的精度問題,當打印小數相加的時候有時候會出現數值不準確的情況,如果是在做一些需要數據精度要求較高的工作的時候稍有不慎就會出現問題 console.log(0.1+0.1) //0.2 console.log(0.1+0.2) //0.3000000000000000...
摘要:是最特殊的類型,表示沒有意義的數,例如。十六進制數八進制數十進制數十六進制數對于部分情況,和存在分歧。例如,表示希臘字符關于字符串的轉換,其實核心就是函數,如果是數字型,還可以添加參數,使之變為二進制八進制十進制十六進制數。 雖然目前已經算是ES6的時代,然是ES5的尾巴仍在眾多框架中出現,JS我雖然通過視頻等方式學習,曾經做過項目,但是仍對部分細節和原理不了解,通過閱讀這本書,希望能...
閱讀 1830·2021-11-11 16:54
閱讀 2056·2019-08-30 15:56
閱讀 2365·2019-08-30 15:44
閱讀 1282·2019-08-30 15:43
閱讀 1856·2019-08-30 11:07
閱讀 812·2019-08-29 17:11
閱讀 1464·2019-08-29 15:23
閱讀 3007·2019-08-29 13:01