亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JavaScript浮點(diǎn)運(yùn)算0.2+0.1 !== 0.3

iflove / 1934人閱讀

摘要:標(biāo)準(zhǔn)二進(jìn)制浮點(diǎn)數(shù)算法就是一個(gè)對(duì)實(shí)數(shù)進(jìn)行計(jì)算機(jī)編碼的標(biāo)準(zhǔn)。然后把取出的整數(shù)部分按順序排列起來,先取的整數(shù)作為二進(jìn)制小數(shù)的高位有效位,后取的整數(shù)作為低位有效位。

浮點(diǎn)運(yùn)算JavaScript

本文主要討論JavaScript的浮點(diǎn)運(yùn)算,主要包括

JavaScript number基本類型

二進(jìn)制表示十進(jìn)制

浮點(diǎn)數(shù)的精度

number 數(shù)字類型

在JavaScript中,數(shù)字只有number這一種類型;

var intS = 2,
    floatA = 0.1;
typeof intS;   // number
typeof floatA; //number

那么這個(gè)情況下應(yīng)該很容易理解一件事情:number應(yīng)該是實(shí)現(xiàn)的浮點(diǎn)型數(shù)來標(biāo)識(shí)所有的數(shù);
而實(shí)際上也是這樣;JavaScript的number類型按照ECMA的JavaScript標(biāo)準(zhǔn),它的Number類型就是IEEE 754的雙精度數(shù)值,相當(dāng)于java的double類型。IEEE 754標(biāo)準(zhǔn)《二進(jìn)制浮點(diǎn)數(shù)算法》(www.ieee.org)就是一個(gè)對(duì)實(shí)數(shù)進(jìn)行計(jì)算機(jī)編碼的標(biāo)準(zhǔn)。

十進(jìn)制轉(zhuǎn)換為二進(jìn)制

同樣,在計(jì)算機(jī)的世界里,應(yīng)該是只有二進(jìn)制數(shù)據(jù)的,不是0就是1,那么為了表達(dá)生活中最為常見的十進(jìn)制數(shù)據(jù),就會(huì)有個(gè)轉(zhuǎn)換過程;這個(gè)就是十進(jìn)制轉(zhuǎn)換為二進(jìn)制的方法;
參考:http://www.cnblogs.com/xkfz00...

十進(jìn)制整數(shù)轉(zhuǎn)換為二進(jìn)制

這個(gè)情況比較常見:3 =》 01;5 =》101;十進(jìn)制整數(shù)轉(zhuǎn)換為二進(jìn)制整數(shù)采用"除2取余,逆序排列"法。具體做法是:用2去除十進(jìn)制整數(shù),可以得到一個(gè)商和余數(shù);再用2去除商,又會(huì)得到一個(gè)商和余數(shù),如此進(jìn)行,直到商為零時(shí)為止,然后把先得到的余數(shù)作為二進(jìn)制數(shù)的低位有效位,后得到的余數(shù)作為二進(jìn)制數(shù)的高位有效位,依次排列起來
換算的法則是,使用一個(gè)十進(jìn)制數(shù)字來示例: 173 =》 10101101:

十進(jìn)制小數(shù)變?yōu)槎M(jìn)制

十進(jìn)制的小數(shù)轉(zhuǎn)換為二進(jìn)制,0.5 =》 0.1 ;十進(jìn)制小數(shù)轉(zhuǎn)換成二進(jìn)制小數(shù)采用"乘2取整,順序排列"法。具體做法是:用2乘十進(jìn)制小數(shù),可以得到積,將積的整數(shù)部分取出,再用2乘余下的小數(shù) 部分,又得到一個(gè)積,再將積的整數(shù)部分取出,如此進(jìn)行,直到積中的小數(shù)部分為零,或者達(dá)到所要求的精度為止。然后把取出的整數(shù)部分按順序排列起來,先取的整數(shù)作為二進(jìn)制小數(shù)的高位有效位,后取的整數(shù)作為低位有效位。
示例 0.8125 =》 0.1101

完整的十進(jìn)制小數(shù)轉(zhuǎn)為二進(jìn)制

從上面的講述中可以知道,一個(gè)十進(jìn)制的小數(shù):173.8125 轉(zhuǎn)換為二進(jìn)制是 10101101.1101;在計(jì)算機(jī)中一般都會(huì)使用科學(xué)計(jì)算來處理浮點(diǎn)數(shù),也就是 173.8125 == 1.738125 * 10(2);那么二進(jìn)制的表示也不例外,通過指數(shù)來定位小數(shù)點(diǎn),用固定的精度來表示數(shù)據(jù);

在JavaScript使用的IEEE 754的雙精度數(shù)值,一個(gè)JavaScript的number表示應(yīng)該是二進(jìn)制如下格式:

 1[-/+] 11[位指數(shù)]        52[數(shù)值]                 64位長(zhǎng)
+  -  + -------- + ----------------------- +

64位的具體表述在不同系統(tǒng)可能順序會(huì)有差異,但是都是包含以下三部分:

符號(hào)位: 1bit,0表示正數(shù),1表示負(fù)數(shù)

指數(shù)位:11bit,也就是需要移動(dòng)的位數(shù),也就是指數(shù)的大??;由于會(huì)存在負(fù)數(shù)和證書,所以這里用了一個(gè)偏移的方式處理,也就是真正的指數(shù)+1023,這樣的話就表示了【-1023 ~ 1024】;而-1023也就是全0,1024就是全1;

尾數(shù):52bit,這里需要注意的是由于小數(shù)點(diǎn)前面以為必須為1,所以實(shí)際上是52+1=53位;

參考:http://coolcao.com/2016/10/12...
http://www.cnblogs.com/kingwo...
可以看到,由于二進(jìn)制的精確位數(shù)只有52+1位,那么類似 1/3 這樣的無理數(shù),那么肯定是無法表示的,而且二進(jìn)制還有很多有理數(shù) 0.1這樣的也無法在52位精度的范圍內(nèi)表示精確無誤;都會(huì)被截取53位以后的所有數(shù)字。

0.1+0.2 !== 0.3 [true]

有了以上的鋪墊,那么我們很容易就可以推到出原因了;推理步驟如下:

十進(jìn)制0.1 =》 [利用上面說的方法來轉(zhuǎn)換,乘以2取整數(shù),然后順序獲取取出得數(shù)]

 =>二進(jìn)制為:0.0001100110011[0011…](循環(huán)0011,無限循環(huán))   
 =>指數(shù)表示:尾數(shù)為1.1001100110011001100…1100(共52位,除了小數(shù)點(diǎn)左邊的必須為1的數(shù)據(jù)),指數(shù)為-4(-4+1023 = 1019 二進(jìn)制移碼為 01111111011),符號(hào)位為0  
 => 計(jì)算機(jī)存儲(chǔ)為:0 01111111011 10011001100110011…11001  
 => 因?yàn)槲矓?shù)最多52位,所以實(shí)際存儲(chǔ)的值為0.00011001100110011001100110011001100110011001100110011001  

而十進(jìn)制0.2

 => 二進(jìn)制0.0011001100110011…(循環(huán)0011)  
 =>尾數(shù)為1.1001100110011001100…1100(共52位,除了小數(shù)點(diǎn)左邊的1),指數(shù)為-3(-3+1023=1020二進(jìn)制移碼為01111111100),符號(hào)位為0  
 => 存儲(chǔ)為:0 01111111100 10011001100110011…11001  
 因?yàn)槲矓?shù)最多52位,所以實(shí)際存儲(chǔ)的值為0.00110011001100110011001100110011001100110011001100110011  

 那么兩者相加得:
加法運(yùn)算的時(shí)候需要注意以下幾點(diǎn):

對(duì)階:需要將指數(shù)小的,變得和指數(shù)大的一樣,通過位數(shù)移位【移位注意有一個(gè)隱藏的小數(shù)點(diǎn)左邊的固定的1】

尾數(shù)運(yùn)算:加法運(yùn)算

結(jié)果規(guī)格化:規(guī)范為 位數(shù)的左邊第一位必須為隱藏的1,

舍入處理:主要是在截取的時(shí)候進(jìn)行的處理,最后位舍去時(shí)為0直接舍去,為1則+1;【有多種舍入處理】

溢出判斷:

尾數(shù)加法運(yùn)算開始,注意小數(shù)點(diǎn)左邊隱藏的默認(rèn)1

   [1].1001100110011001100110011001100110011001100110011001
 + [1].1001100110011001100110011001100110011001100110011001

//由于0.1是-3階,指數(shù)是-4,而0.2的指數(shù)位-3,故而取大者-3;這樣0.1需要右移一位,剛好之前小數(shù)點(diǎn)左側(cè)隱藏的1被移出來了;如下

      .1100110011001100110011001100110011001100110011001100 【1被舍去】
+  [1].1001100110011001100110011001100110011001100110011001
=   100110011001100110011001100110011001100110011001100111

此時(shí)階碼變?yōu)榱?-3,但是由于進(jìn)位了兩位,但是最高位需要保留,故而階位只是+1,也就是-2了.也就是01111111101,
進(jìn)行舍入處理,由于最高位一定是1,所以對(duì)結(jié)果最高位去除,末尾一位去除,由于是1,故而+1處理,得到新的52位位數(shù)為:

 新的尾數(shù): 0011001100110011001100110011001100110011001100110100
存儲(chǔ)為: 0  01111111101  0011001100110011001100110011001100110011001100110100
十進(jìn)制就是:0.3000000000000000444089209850062616169452667236328125
截取為:   0.30000000000000004  

轉(zhuǎn)換成10進(jìn)制之后得到:0.30000000000000004

思考

看到 0.1+0.2 = 0.30000000000000004;我開始慌了,那么0.1+0.3 === 0.4 對(duì)嗎?我也不知道,雖然最后運(yùn)算的時(shí)候證明是對(duì)的,但是還是可以按照我們的方法進(jìn)行分析

 十進(jìn)制0.1  [利用上面說的方法來轉(zhuǎn)換,乘以2取整數(shù),然后順序獲取取出得數(shù)]
 =>二進(jìn)制為:0.0001100110011[0011…](循環(huán)0011,無限循環(huán))   
 =>指數(shù)表示:尾數(shù)為1.1001100110011001100…1100(共52位,除了小數(shù)點(diǎn)左邊的必須為1的數(shù)據(jù)),指數(shù)為-4(-4+1023 = 1019 二進(jìn)制移碼為 01111111011),符號(hào)位為0  
 => 計(jì)算機(jī)存儲(chǔ)為:0 01111111011 10011001100110011…11001  
 => 因?yàn)槲矓?shù)最多52位,所以實(shí)際存儲(chǔ)的值為0.00011001100110011001100110011001100110011001100110011001 
 
 而十進(jìn)制0.3  
 => 二進(jìn)制0.010011001100110011001100110011001...(循環(huán)1001)  
 =>尾數(shù)為1.00110011001100110011…0011(共52位,除了小數(shù)點(diǎn)左邊的1),指數(shù)為-2(-2+1023=1021二進(jìn)制移碼為01111111101),符號(hào)位為0  
 => 存儲(chǔ)為:0 01111111101 0011001100110011…110011  
 因?yàn)槲矓?shù)最多52位,所以實(shí)際存儲(chǔ)的值為0.01001100110011001100110011001100110011001100110011001100  

 那么兩者相加得[對(duì)階,為大者-2,-4階數(shù)的0.1左移兩位]:      
     .0110011001100110011001100110011001100110011001100110
+ [1].0011001100110011001100110011001100110011001100110011 
=   1.1001100110011001100110011001100110011001100110011001

新的尾數(shù): 1001100110011001100110011001100110011001100110011001
存儲(chǔ)為: 0  01111111101  1001100110011001100110011001100110011001100110011001
十進(jìn)制就是:0.39999999999999996447286321199499070644378662109375
截取為:   0.4 

可以看到,JavaScript的小數(shù)保留了17位,

//一個(gè)52位小數(shù)的最小二進(jìn)制的表示
0.0000000000000000000000000000000000000000000000000001
0.0000000000000002220446049250313 
//一個(gè)53【加頭部默認(rèn)1位】位小數(shù)的最小二進(jìn)制數(shù)
0.00000000000000000000000000000000000000000000000000001
0.00000000000000011102230246251565
Math.pow(2, 53)
9007199254740992 //當(dāng)大于這個(gè)數(shù)的時(shí)候就會(huì)丟失精度
Math.pow(2, -53)
1.1102230246251565e-16  //當(dāng)小于這個(gè)數(shù)也會(huì)丟失精度

JavaScript采用了17位來默認(rèn)截取數(shù)據(jù),根據(jù)四舍五入方法或者是說二進(jìn)制中的0舎1進(jìn)位的方式截取。
所以這樣的加法有的時(shí)候會(huì)出現(xiàn)精度問題,有的又不會(huì)??纯淳唧w的情況,在chrome的console里面運(yùn)行的結(jié)果如下:

0.4-0.1
0.30000000000000004

0.3+0.1
0.4

0.1+0.2
0.30000000000000004

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/84663.html

相關(guān)文章

  • 關(guān)于 JavaScript 浮點(diǎn)運(yùn)算的精度解決方案

    摘要:原因至于問題產(chǎn)生的原因,或者關(guān)于問題的更詳細(xì)的描述,大家請(qǐng)看下面幾個(gè)文章浮點(diǎn)運(yùn)算浮點(diǎn)值運(yùn)算舍入誤差基礎(chǔ)浮點(diǎn)數(shù)四則運(yùn)算精度丟失問題解決方案這里主要討論一下解決方案的問題,上面幾篇文章的解決思路,都是重寫加法減法乘法和除法運(yùn)算。 問題背景 在 chrome 瀏覽器中調(diào)出開發(fā)者工具,在控制臺(tái)窗口輸入下面的表達(dá)式: 0.1 + 0.2 // 期望:0.3,結(jié)果:0.300...

    jsyzchen 評(píng)論0 收藏0
  • 為什么JavaScript里面0.1+0.2 === 0.3是false

    摘要:返回是,這是為什么呢我們知道浮點(diǎn)數(shù)計(jì)算是不精確的,上面的返回式實(shí)際上是這樣的在的新規(guī)范加入了一個(gè)新的東西是在對(duì)象上面,新增一個(gè)極小的常量。根據(jù)規(guī)格,它表示與大于的最小浮點(diǎn)數(shù)之間的差。上面的代碼為浮點(diǎn)數(shù)運(yùn)算,部署了一個(gè)誤差檢查函數(shù)。 0.1+0.2 === 0.3 //返回是false, 這是為什么呢?? 我們知道浮點(diǎn)數(shù)計(jì)算是不精確的,上面的返回式實(shí)際上是這樣的:0.1 + 0.2 = ...

    nicercode 評(píng)論0 收藏0
  • JS數(shù)值

    摘要:由于浮點(diǎn)數(shù)不是精確的值,所以涉及小數(shù)的比較和運(yùn)算要特別小心。根據(jù)標(biāo)準(zhǔn),位浮點(diǎn)數(shù)的指數(shù)部分的長(zhǎng)度是個(gè)二進(jìn)制位,意味著指數(shù)部分的最大值是的次方減。也就是說,位浮點(diǎn)數(shù)的指數(shù)部分的值最大為。 一 前言 這篇文章主要解決以下三個(gè)問題: 問題1:浮點(diǎn)數(shù)計(jì)算精確度的問題 0.1 + 0.2; //0.30000000000000004 0.1 + 0.2 === 0.3; // ...

    williamwen1986 評(píng)論0 收藏0
  • JS中如何理解浮點(diǎn)數(shù)?

    摘要:本文通過介紹的二進(jìn)制存儲(chǔ)標(biāo)準(zhǔn)來理解浮點(diǎn)數(shù)運(yùn)算精度問題,和理解對(duì)象的等屬性值是如何取值的,最后介紹了一些常用的浮點(diǎn)數(shù)精度運(yùn)算解決方案。浮點(diǎn)數(shù)精度運(yùn)算解決方案關(guān)于浮點(diǎn)數(shù)運(yùn)算精度丟失的問題,不同場(chǎng)景可以有不同的解決方案。 本文由云+社區(qū)發(fā)表 相信大家在平常的 JavaScript 開發(fā)中,都有遇到過浮點(diǎn)數(shù)運(yùn)算精度誤差的問題,比如 console.log(0.1+0.2===0.3)// fa...

    bang590 評(píng)論0 收藏0
  • 為什么0.1+0.2不等于0.3

    摘要:又如,對(duì)于,結(jié)果其實(shí)并不是,但是最接近真實(shí)結(jié)果的數(shù),比其它任何浮點(diǎn)數(shù)都更接近。許多語(yǔ)言也就直接顯示結(jié)果為了,而不展示一個(gè)浮點(diǎn)數(shù)的真實(shí)結(jié)果了。小結(jié)本文主要介紹了浮點(diǎn)數(shù)計(jì)算問題,簡(jiǎn)單回答了為什么以及怎么辦兩個(gè)問題為什么不等于。 原文地址:為什么0.1+0.2不等于0.3 先看兩個(gè)簡(jiǎn)單但詭異的代碼: 0.1 + 0.2 > 0.3 // true 0.1 * 0.1 = 0.01000000...

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

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

0條評(píng)論

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