日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript浮点运算0.2+0.1 !== 0.3

發布時間:2023/11/29 javascript 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript浮点运算0.2+0.1 !== 0.3 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

浮點運算JavaScript

本文主要討論JavaScript的浮點運算,主要包括

  • JavaScript number基本類型

  • 二進制表示十進制

  • 浮點數的精度

number 數字類型

在JavaScript中,數字只有number這一種類型;

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

那么這個情況下應該很容易理解一件事情:number應該是實現的浮點型數來標識所有的數;
而實際上也是這樣;JavaScript的number類型按照ECMA的JavaScript標準,它的Number類型就是IEEE 754的雙精度數值,相當于java的double類型。IEEE 754標準《二進制浮點數算法》(www.ieee.org)就是一個對實數進行計算機編碼的標準。

十進制轉換為二進制

同樣,在計算機的世界里,應該是只有二進制數據的,不是0就是1,那么為了表達生活中最為常見的十進制數據,就會有個轉換過程;這個就是十進制轉換為二進制的方法;
參考:http://www.cnblogs.com/xkfz00...

十進制整數轉換為二進制

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

十進制小數變為二進制

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

完整的十進制小數轉為二進制

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

在JavaScript使用的IEEE 754的雙精度數值,一個JavaScript的number表示應該是二進制如下格式:

1[-/+] 11[位指數] 52[數值] 64位長 + - + -------- + ----------------------- +

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

  • 符號位: 1bit,0表示正數,1表示負數

  • 指數位:11bit,也就是需要移動的位數,也就是指數的大小;由于會存在負數和證書,所以這里用了一個偏移的方式處理,也就是真正的指數+1023,這樣的話就表示了【-1023 ~ 1024】;而-1023也就是全0,1024就是全1;

  • 尾數:52bit,這里需要注意的是由于小數點前面以為必須為1,所以實際上是52+1=53位;

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

    0.1+0.2 !== 0.3 [true]

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

    十進制0.1 =》 [利用上面說的方法來轉換,乘以2取整數,然后順序獲取取出得數]

    =>二進制為:0.0001100110011[0011…](循環0011,無限循環) =>指數表示:尾數為1.1001100110011001100…1100(共52位,除了小數點左邊的必須為1的數據),指數為-4(-4+1023 = 1019 二進制移碼為 01111111011),符號位為0 => 計算機存儲為:0 01111111011 10011001100110011…11001 => 因為尾數最多52位,所以實際存儲的值為0.00011001100110011001100110011001100110011001100110011001

    而十進制0.2

    => 二進制0.0011001100110011…(循環0011) =>尾數為1.1001100110011001100…1100(共52位,除了小數點左邊的1),指數為-3(-3+1023=1020二進制移碼為01111111100),符號位為0 => 存儲為:0 01111111100 10011001100110011…11001 因為尾數最多52位,所以實際存儲的值為0.00110011001100110011001100110011001100110011001100110011

     那么兩者相加得:
    加法運算的時候需要注意以下幾點:

    • 對階:需要將指數小的,變得和指數大的一樣,通過位數移位【移位注意有一個隱藏的小數點左邊的固定的1】

    • 尾數運算:加法運算

    • 結果規格化:規范為 位數的左邊第一位必須為隱藏的1,

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

    • 溢出判斷:

    尾數加法運算開始,注意小數點左邊隱藏的默認1

    [1].1001100110011001100110011001100110011001100110011001+ [1].1001100110011001100110011001100110011001100110011001

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

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

    此時階碼變為了 -3,但是由于進位了兩位,但是最高位需要保留,故而階位只是+1,也就是-2了.也就是01111111101,
    進行舍入處理,由于最高位一定是1,所以對結果最高位去除,末尾一位去除,由于是1,故而+1處理,得到新的52位位數為:

    新的尾數: 0011001100110011001100110011001100110011001100110100 存儲為: 0 01111111101 0011001100110011001100110011001100110011001100110100 十進制就是:0.3000000000000000444089209850062616169452667236328125 截取為: 0.30000000000000004

    轉換成10進制之后得到:0.30000000000000004

    思考

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

    十進制0.1 [利用上面說的方法來轉換,乘以2取整數,然后順序獲取取出得數]=>二進制為:0.0001100110011[0011…](循環0011,無限循環) =>指數表示:尾數為1.1001100110011001100…1100(共52位,除了小數點左邊的必須為1的數據),指數為-4(-4+1023 = 1019 二進制移碼為 01111111011),符號位為0 => 計算機存儲為:0 01111111011 10011001100110011…11001 => 因為尾數最多52位,所以實際存儲的值為0.00011001100110011001100110011001100110011001100110011001 而十進制0.3 => 二進制0.010011001100110011001100110011001...(循環1001) =>尾數為1.00110011001100110011…0011(共52位,除了小數點左邊的1),指數為-2(-2+1023=1021二進制移碼為01111111101),符號位為0 => 存儲為:0 01111111101 0011001100110011…110011 因為尾數最多52位,所以實際存儲的值為0.01001100110011001100110011001100110011001100110011001100 那么兩者相加得[對階,為大者-2,-4階數的0.1左移兩位]: .0110011001100110011001100110011001100110011001100110 + [1].0011001100110011001100110011001100110011001100110011  = 1.1001100110011001100110011001100110011001100110011001新的尾數: 1001100110011001100110011001100110011001100110011001 存儲為: 0 01111111101 1001100110011001100110011001100110011001100110011001 十進制就是:0.39999999999999996447286321199499070644378662109375 截取為: 0.4

    可以看到,JavaScript的小數保留了17位,

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

    JavaScript采用了17位來默認截取數據,根據四舍五入方法或者是說二進制中的0舎1進位的方式截取。
    所以這樣的加法有的時候會出現精度問題,有的又不會。看看具體的情況,在chrome的console里面運行的結果如下:

    0.4-0.1 0.300000000000000040.3+0.1 0.40.1+0.2 0.30000000000000004 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的JavaScript浮点运算0.2+0.1 !== 0.3的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。