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