摘要:本篇文章會講述浮點數的設計原理,比如如何存儲二進制的問題,從而幫助我們更好的編碼。
__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