国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JS中如何理解浮點(diǎn)數(shù)?

bang590 / 2697人閱讀

摘要:本文通過(guò)介紹的二進(jìn)制存儲(chǔ)標(biāo)準(zhǔn)來(lái)理解浮點(diǎn)數(shù)運(yùn)算精度問(wèn)題,和理解對(duì)象的等屬性值是如何取值的,最后介紹了一些常用的浮點(diǎn)數(shù)精度運(yùn)算解決方案。浮點(diǎn)數(shù)精度運(yùn)算解決方案關(guān)于浮點(diǎn)數(shù)運(yùn)算精度丟失的問(wèn)題,不同場(chǎng)景可以有不同的解決方案。

本文由云+社區(qū)發(fā)表

相信大家在平常的 JavaScript 開(kāi)發(fā)中,都有遇到過(guò)浮點(diǎn)數(shù)運(yùn)算精度誤差的問(wèn)題,比如 console.log(0.1+0.2===0.3)// false。在 JavaScript 中,所有的數(shù)字包括整數(shù)和小數(shù)都是用 Number 類型來(lái)表示的。本文通過(guò)介紹 Number 的二進(jìn)制存儲(chǔ)標(biāo)準(zhǔn)來(lái)理解浮點(diǎn)數(shù)運(yùn)算精度問(wèn)題,和理解 Number 對(duì)象的 MAX_VALUE 等屬性值是如何取值的,最后介紹了一些常用的浮點(diǎn)數(shù)精度運(yùn)算解決方案。

Number 的存儲(chǔ)標(biāo)準(zhǔn)

JavaScript Number 采用的是 IEEE 754 定義的 64 位雙精度浮點(diǎn)型來(lái)表示。具體的字節(jié)分配可以先看一下引自維基百科的圖:

從上圖中可以看到,從高到低,64位被分成3段,分別是:

sign: 符號(hào)位,占 1 位;

exponent: 指數(shù)位,占 11 位;

fraction: 有效數(shù)字位,占 52 位。

指數(shù)位有 11 位,取值范圍是 0 到 2047。當(dāng)指數(shù)位 e=0 或者 e=2017 時(shí),根據(jù)有效數(shù)字位 f 是否為 0 ,具有不同的特殊含義,具體見(jiàn)下表:

對(duì)于常用的 normal number, 為了方便表示指數(shù)為負(fù)數(shù)的情況,所以,指數(shù)位數(shù)值大小做了一個(gè) -1023 的偏移量。對(duì)于一個(gè)非 0 數(shù)字而言,,它的二進(jìn)制的科學(xué)計(jì)數(shù)法里的第一位有效數(shù)字固定是 1。這樣,一個(gè)雙精度浮點(diǎn)型數(shù)字的值就是

對(duì)于 subnormal number,它可以用來(lái)表示更加接近于 0 的數(shù),它特殊的地方是有效數(shù)字位的前面補(bǔ)充的是 0 而不是 1,且指數(shù)為偏移量是 -1022,所以值是:

Number 對(duì)象中的幾個(gè)屬性值

知道了 Number 是如何存儲(chǔ)之后,Number 對(duì)象的屬性是如何取值的就明朗了。

Number.MAX_VALUE:可表示的最大的數(shù),顯然 e 和 f 都取最大時(shí)能表示的數(shù)最大,值為

Number.MIN_VALUE:可表示的最小的正數(shù),用最小的 subnormal number 來(lái)表示。當(dāng) e = 0 ,f 的最后一位為 1,其他為 0 時(shí)最小,值為

Number.EPSILON : 表示 1 與 Number 可表示的大于 1 的最小的浮點(diǎn)數(shù)之間的差值。值為

Number.MAXSAFEINTEGER:表示在 JavaScript 中最大的安全整數(shù)。可以連續(xù)且精確被表示出來(lái)的整數(shù)成為安全整數(shù),比如 2^54 就不是個(gè)安全整數(shù),因?yàn)樗?2^54+1 兩個(gè)數(shù)的表示是完全一樣的,e=1077,f=0。 Math.pow(2,54)===Math.pow(2,54)+1// true。整數(shù)轉(zhuǎn)化為二進(jìn)制后,小數(shù)點(diǎn)后是不會(huì)有數(shù)字的,而用二進(jìn)制的科學(xué)計(jì)數(shù)法表示時(shí),小數(shù)點(diǎn)后最多保留 52 位,加上前置的一個(gè) 1,有 53 位數(shù)字,所以當(dāng)一個(gè)數(shù)轉(zhuǎn)化二進(jìn)制時(shí),如果位數(shù)超過(guò) 53 位,必然會(huì)截?cái)嗄┪驳牟糠郑磳?dǎo)致不能精確表示,即為不安全整數(shù)。所以最小的會(huì)被截?cái)嗟恼麛?shù)是 100...001=2^53+1(中間有52個(gè)0)。這個(gè)數(shù)設(shè)為 X,則比 X 小的整數(shù)都能被精確表示出來(lái),再加上“連續(xù)”這個(gè)條件,所以 X-1 不是我們要的答案,X-2 才是。 Number.MAX_SAFE_INTEGER 最終值為

Number.MINSAFEINTEGER:表示在 JavaScript 中最小的安全整數(shù),對(duì) Number.MAX_SAFE_INTEGER 取負(fù)值即可,值為 -9007199254740991

為什么0.1+0.2不等于0.3

現(xiàn)在看看 console.log(0.1+0.2===0.3)// false 這個(gè)問(wèn)題,數(shù)字 0.1 轉(zhuǎn)化成二進(jìn)制是 0.0001100110011... 即 1.10011001...1001 2^-4 (小數(shù)部分有52位,即有13個(gè)1001循環(huán))。由于第 53 位是 1,類似 10 進(jìn)制的四舍五入,二進(jìn)制是“零舍一入”,所以 0.1 的最終二進(jìn)制科學(xué)計(jì)數(shù)法表示是 1.10011001...1010 2^-4,即二進(jìn)制數(shù)值大小實(shí)際上是 0.000110011001...10011010。下面的代碼驗(yàn)證了這個(gè)值(打印出來(lái)的值,把最末尾的0去掉了):

var a = 0.1;console.log(a.toString(2)); //0.0001100110011001100110011001100110011001100110011001101

同理十進(jìn)制數(shù)字 0.2 轉(zhuǎn)化為二進(jìn)制的最終值是 1.10011001...1010 2^-3 即 0.00110011...100111010;十進(jìn)制 0.3 轉(zhuǎn)化位二進(jìn)制的最終值是 1.00110011...0011 2^-2

var b = 0.2;console.log(b.toString(2)); //0.001100110011001100110011001100110011001100110011001101var c = 0.3;console.log(c.toString(2)); //0.010011001100110011001100110011001100110011001100110011

所以,0.1+0.2 的值即為上面 0.1 和 0.2 對(duì)應(yīng)的二進(jìn)制數(shù)值的相加,如下圖所示

上圖中,對(duì)所得的和,“零舍一入”保留 52 位有效小數(shù)就是最終的值:0.01001100...110100(第 53 位是 1 ,所以往前進(jìn)了 1),如下代碼所示。這個(gè)值與上文中的 0.3 的最終二進(jìn)制表示的值明顯不相同,即解釋了 0.1 + 0.2 不等于 0.3 的根本原因所在(實(shí)際上,這個(gè)值轉(zhuǎn)化為 10 進(jìn)制約等于 0.30000000000000004)。注:打印出來(lái)的長(zhǎng)度是 54,因?yàn)橛?52 位有效小數(shù),前面是"0.01",長(zhǎng)度是 4,最后去掉末尾的 2 個(gè) 0,所以最后打印出來(lái)的長(zhǎng)度是 52+4-2 = 54。

var d = 0.1 + 0.2;console.log(d.toString(2)); //0.0100110011001100110011001100110011001100110011001101console.log(d.toString(2).length); // 54
浮點(diǎn)數(shù)精度運(yùn)算解決方案

關(guān)于 js 浮點(diǎn)數(shù)運(yùn)算精度丟失的問(wèn)題,不同場(chǎng)景可以有不同的解決方案。 1、如果只是用來(lái)展示一個(gè)浮點(diǎn)數(shù)的結(jié)果,則可以借用 Number 對(duì)象的 toFixed 和 parseFloat 方法。下面代碼片段中,fixed 參數(shù)表示要保留幾位小數(shù),可以根據(jù)實(shí)際場(chǎng)景調(diào)整精度。

function formatNum(num, fixed = 10) {    return parseFloat(a.toFixed(fixed))}var a = 0.1 + 0.2;console.log(formatNum(a)); //0.3

2、如果需要進(jìn)行浮點(diǎn)數(shù)的加減乘除等運(yùn)算,由上文可知,在小于 Number.MAXSAFEINTEGER 范圍的整數(shù)是可以被精確表示出來(lái)的,所以可以先把小數(shù)轉(zhuǎn)化為整數(shù),運(yùn)算得到結(jié)果后再轉(zhuǎn)化為對(duì)應(yīng)的小數(shù)。比如兩個(gè)浮點(diǎn)數(shù)的加法:

 function add(num1, num2) {  var decimalLen1 = (num1.toString().split(".")[1] || "").length; //第一個(gè)參數(shù)的小數(shù)個(gè)數(shù)  var decimalLen2 = (num2.toString().split(".")[1] || "").length; //第二個(gè)參數(shù)的小數(shù)個(gè)數(shù)  var baseNum = Math.pow(10, Math.max(decimalLen1, decimalLen2));  return (num1 * baseNum + num2 * baseNum) / baseNum;}console.log(add(0.1 , 0.2)); //0.3

參考資料

https://en.wikipedia.org/wiki...

https://en.wikipedia.org/wiki...

https://en.wikipedia.org/wiki...

https://en.wikipedia.org/wiki...

此文已由作者授權(quán)騰訊云+社區(qū)發(fā)布

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/108833.html

相關(guān)文章

  • JS魔法堂:徹底理解0.1 + 0.2 === 0.30000000000000004的背后

    摘要:也就是說(shuō)不僅是會(huì)產(chǎn)生這種問(wèn)題,只要是采用的浮點(diǎn)數(shù)編碼方式來(lái)表示浮點(diǎn)數(shù)時(shí),則會(huì)產(chǎn)生這類問(wèn)題。到這里我們都理解只要采取的浮點(diǎn)數(shù)編碼的語(yǔ)言均會(huì)出現(xiàn)上述問(wèn)題,只是它們的標(biāo)準(zhǔn)類庫(kù)已經(jīng)為我們提供了解決方案而已。 Brief 一天有個(gè)朋友問(wèn)我JS中計(jì)算0.7 * 180怎么會(huì)等于125.99999999998,坑也太多了吧!那時(shí)我猜測(cè)是二進(jìn)制表示數(shù)值時(shí)發(fā)生round-off error所導(dǎo)致,但并不...

    JerryWangSAP 評(píng)論0 收藏0
  • 你對(duì)Number一無(wú)所知

    摘要:表示正數(shù),表示負(fù)數(shù)。是一個(gè)無(wú)符號(hào)整數(shù),因?yàn)殚L(zhǎng)度是位,取值范圍是。浮點(diǎn)數(shù)具體數(shù)值的實(shí)際表示。例如對(duì)于單精度浮點(diǎn)數(shù),指數(shù)部分實(shí)際最小值是,對(duì)應(yīng)的尾數(shù)部分從一直到,相鄰兩小浮點(diǎn)數(shù)之間的距離都是而與最近的浮點(diǎn)數(shù)即最小的非規(guī)約數(shù)也是。 二進(jìn)制表示小數(shù) 例如用二進(jìn)制表示 0.8125 0.8125 0.8125*2 = 1.625 取整為 1 0.625*2=1.25 取整為 1 0.25*2=0...

    Hanks10100 評(píng)論0 收藏0
  • 探尋 JavaScript 精度問(wèn)題以及解決方案

    摘要:推導(dǎo)為何等于在中所有數(shù)值都以標(biāo)準(zhǔn)的雙精度浮點(diǎn)數(shù)進(jìn)行存儲(chǔ)的。先來(lái)了解下標(biāo)準(zhǔn)下的雙精度浮點(diǎn)數(shù)。精度位總共是,因?yàn)橛每茖W(xué)計(jì)數(shù)法表示,所以首位固定的就沒(méi)有占用空間。驗(yàn)證完成的最大安全數(shù)是如何來(lái)的根據(jù)雙精度浮點(diǎn)數(shù)的構(gòu)成,精度位數(shù)是。 閱讀完本文可以了解到 0.1 + 0.2 為什么等于 0.30000000000000004 以及 JavaScript 中最大安全數(shù)是如何來(lái)的。 十進(jìn)制小數(shù)轉(zhuǎn)為二...

    YanceyOfficial 評(píng)論0 收藏0
  • 數(shù)字

    摘要:中沒(méi)有浮點(diǎn)數(shù)這種東西,但是你會(huì)發(fā)現(xiàn)這樣一個(gè)問(wèn)題,如下從數(shù)學(xué)角度來(lái)看,你會(huì)覺(jué)得不可思議,這是為什么這就跟浮點(diǎn)數(shù)有關(guān)。 在JavaScript只有一種數(shù)值類型number,它包括整數(shù)和帶小數(shù)的十進(jìn)制數(shù)(這里的整數(shù)有點(diǎn)特殊,指的是沒(méi)有小數(shù)的十進(jìn)制數(shù),所以1.0等同于整數(shù)1)。 一、語(yǔ)法1、js中的小數(shù),多余的零可以省略 let a = .1; // 默認(rèn)為0.1 let b = 1.; ...

    OBKoro1 評(píng)論0 收藏0
  • 該死的IEEE-754點(diǎn)數(shù),說(shuō)「約」就「約」,你的底線呢?以JS的名義來(lái)好好查查你

    摘要:而的浮點(diǎn)數(shù)設(shè)置的偏移值是,因?yàn)橹笖?shù)域表現(xiàn)為一個(gè)非負(fù)數(shù),位,所以,實(shí)際的,所以。這是因?yàn)樗鼈冊(cè)谵D(zhuǎn)為二進(jìn)制時(shí)要舍入部分的不同可能造成的不同舍 IEEE 754 表示:你盡管抓狂、罵娘,但你能完全避開(kāi)我,算我輸。 一、IEEE-754浮點(diǎn)數(shù)捅出的那些婁子 首先我們還是來(lái)看幾個(gè)簡(jiǎn)單的問(wèn)題,能說(shuō)出每一個(gè)問(wèn)題的細(xì)節(jié)的話就可以跳過(guò)了,而如果只能泛泛說(shuō)一句因?yàn)镮EEE754浮點(diǎn)數(shù)精度問(wèn)題,那么下文還是...

    gaosboy 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<