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