摘要:本篇文章會講述浮點數的設計原理,比如如何儲存二進位制的問題,從而幫助我們更好的編碼。
__1. deading code __
console.log(1.0-0.9 == 0.1);
//輸出 false
console.log(1.0-0.9, 0.1);
//輸出 0.09999999999999998 0.1
//所以判斷浮點運算結果前要對引數進行精度縮小,縮小精度會四捨五入。
console.log(parseFloat((1.0-0.9).toFixed(10)) == 0.1);
//輸出 true
console.log(parseFloat((1.0-0.9).toFixed(10)),0.1)
//輸出 0.1 0.1
複製程式碼
所以使用 JavaScript 設計浮點數計算時,要考慮小數不準確的問題。
2.浮點數二進位制儲存
如 32 儲存為例來講解儲存。
Sign | Exponent | Mantissa |
---|---|---|
1bit | 8bits | 23bits |
- Sign:表示浮點數是正數還是負數。__0__表示正數,__1__表示負數
- Exponent:指數部分。類似於科學技術法中的M*10^__N__中的 N,要注意規定 01111111 = 2^0 也就是 0,所以指數部分可以表達: -128 - 127。
- Mantissa:基數部分。浮點數具體數值的實際表示。
嘗試把 3.1 轉換成二進位制儲存:
- 是正數第一位是 0。
- 3 轉換成二進位制 11。
- 0.1 轉換成二進位制,__0.1 __ 轉換成 0.0625+0.007825+0.00390625... 即 2^-3+2^-4+2^7....,二進位制為 .00011001100110011001100 ,是1100無限迴圈,保留到23位。(這裡確實有點繞,不理解的單獨查資料能更快了解。也就是這裡導致小數在計算機裡的儲存會不準確,是一個近似值。
- 整數和小數合併為 11.0001100110011001100110 , 然後保證小數點以前只有一位數,1.10001100110011001100110 * 2^1。
- 合併後小數點前的一位數是要捨去的,由於我們上一個步驟,小數點前的數字總會為 1,所以為了減少儲存我們捨去 . 前的為1數字,最後得 .100011001100110011001100 * 2^1。
- 指數轉換,由上一步得指數為 __2^1 __,由於規定 01111111 = 2^0(這樣的目的就是為了,指數可以為正也可以為負), 2^1 為 10000000 ,合併後得 10000000 10001100110011001100110
- 添上第一位代表正負 0 10000000 10001100110011001100110 最終__ 3.1 __被用二進位制表達。
其中最重要的部分是小數轉二進位制,像 0.5、0.25、0.125 這樣的小數轉化二進位制為 0.1、0.01、0.001 ,但是 0.1、0.2 就不好表示了。如果不理解百度有線上二轉十進位制 地址
驗證的網址:https://www.h-schmidt.net/FloatConverter/IEEE754.html
3.猜想
語言還沒有組織好。
我的部落格:http://liangtongzhuo.com