分享這篇筆記的目的是想驅(qū)動(dòng)自己多動(dòng)手栈雳,多動(dòng)腦护奈,開(kāi)放自己,認(rèn)識(shí)別人哥纫。如有問(wèn)題霉旗,請(qǐng)指正。
從整數(shù)到小數(shù)
先回憶下如何用二進(jìn)制表示十進(jìn)制整數(shù)蛀骇。例如厌秒,。
以此類推松靡,
简僧。
這樣的表示方法,會(huì)被我們理所應(yīng)當(dāng)?shù)叵氲降衿邸5沁@樣表示小數(shù)存在不足岛马。
存在的問(wèn)題
- 能精確表示的小數(shù)有限棉姐,只能表示 被表示的數(shù)字。如1/3啦逆、 1/5等無(wú)法被上述方式表示伞矩。
- 在定長(zhǎng)位數(shù)下(float是32位),不能同時(shí)表示極大數(shù)和及其接近0的數(shù)夏志。(ps乃坤,如果小數(shù)點(diǎn)不定位置,那么要描述小數(shù)點(diǎn)位置又需要額外的位數(shù)沟蔑,更加浪費(fèi)空間)湿诊。
IEEE標(biāo)準(zhǔn)表示浮點(diǎn)數(shù)
要解決的問(wèn)題:在給定區(qū)間內(nèi),整數(shù)有限個(gè)瘦材,但實(shí)數(shù)無(wú)限個(gè)
基本矛盾:有限個(gè)二進(jìn)制位去表示無(wú)限多的實(shí)數(shù)
表示:使用類似科學(xué)計(jì)數(shù)法方式表示厅须。
本文只談float32類型情況下。
表示公式
這樣的表示小數(shù)點(diǎn)是浮動(dòng)的食棕,所以稱為浮點(diǎn)數(shù)朗和。(相對(duì)的,小數(shù)點(diǎn)確定的叫做定點(diǎn)數(shù)簿晓,整數(shù)也是一種定點(diǎn)數(shù))
S:標(biāo)志位(1位)眶拉,大家都懂
E:階碼(8位),作用是對(duì)浮點(diǎn)數(shù)加權(quán)
F:尾數(shù)(23位)憔儿,這個(gè)數(shù)有些特別忆植,它的取值范圍[1,2)或[0,1),倆個(gè)取值范圍跟E的取值相關(guān)皿曲,后文詳細(xì)解釋唱逢。
階碼E 和 尾數(shù)F 的取值
階碼狀態(tài) | 尾數(shù)狀態(tài) | 值的表示 | 備注 |
---|---|---|---|
E∈(0,255) | 任意 | 規(guī)格化 | |
E=0 | 任意 | 非規(guī)格化 | |
E=255 | 0 | 無(wú)窮大吴侦、小 | |
E=255 | ≠0 | NaN |
1.規(guī)格化情況
階碼E的二進(jìn)制位既不全是0屋休,也不全是1。
因?yàn)镋∈(0,255)的备韧,E-127 剛好平分E的值域劫樟。這樣,E既可以表示正指數(shù)织堂,也可表示副指數(shù)叠艳。
尾數(shù)F的值域[1,2)
2. 非規(guī)格化情況
階碼E的二進(jìn)制位全0
尾數(shù)F的值域[0,1)
階碼E和尾數(shù)F的含義
這樣的表示公式是非常反直覺(jué)的,為什么要將非規(guī)格化情況單獨(dú)提出易阳,這驅(qū)使我探究其中含義附较。
階碼E
先定義階數(shù)組。根據(jù)E取值不同潦俺,的值可以組成的數(shù)組是階數(shù)組拒课,階數(shù)組可見(jiàn)下表
階數(shù)組元素 | 元素值 |
---|---|
A[0] | |
A[1] | |
A[2] | |
A[3] | |
…… | …… |
A[127] | |
A[128] | |
…… | …… |
A[253] | |
A[254] | |
A[255] | ∞ |
階碼E就是階數(shù)組的序號(hào)(數(shù)組下標(biāo))
階數(shù)組元素算出后徐勃,每個(gè)階的值域也我們自然能算出。
階數(shù)組元素 | 元素值 | 表示范圍 | 精度 |
---|---|---|---|
A[0] | |||
A[1] | |||
A[2] | |||
A[3] | |||
…… | …… | …… | …… |
A[127] | |||
A[128] | |||
…… | …… | …… | …… |
A[150] | |||
…… | …… | …… | …… |
A[254] | |||
A[255] | ∞ | - |
這樣的表示早像,就將整個(gè)實(shí)數(shù)域都囊括了僻肖。非規(guī)格化情況(A[0]階),巧妙地填充了0附近的空白卢鹦。
尾數(shù)F
尾數(shù)F理解成一個(gè)分?jǐn)?shù)的分子臀脏,分母是,分?jǐn)?shù)的“1”是E階的值域冀自。打個(gè)比方揉稚,一條線段的長(zhǎng)度為A[E],平均分成2^23段熬粗,取其前F段窃植。
計(jì)算出浮點(diǎn)數(shù)的階號(hào)E和尾數(shù)F
計(jì)算F時(shí),采用二分法荐糜。
下面以 N=25f 進(jìn)行舉例
1.找到N的階碼
2.二分法找尾數(shù)F
判斷 | Y or N | F從右向左的二進(jìn)制占位 |
---|---|---|
IF 25 >=24 | Y | 1 |
IF 25 >=28 | N | 10 |
IF 25 >=26 | N | 100 |
IF 25 >=25 | Y | 1001 |
解釋一下巷怜,階區(qū)間[24,25),中位數(shù)的十進(jìn)制表示是24暴氏,25>24延塑,判斷為真,F(xiàn)的最高位填1答渔。
剩余區(qū)間中位數(shù)28关带,25<28,判斷為假沼撕,F(xiàn)的下一位填0宋雏。依次類推,最終F為1001時(shí)务豺。
所以最終25f的二進(jìn)制表示為:
高16位:0 1000 0011 1001 000
低16位:0000 0000 0000 0000
十六進(jìn)制表示:41 C8 00 00
浮點(diǎn)數(shù)表示帶來(lái)的精度問(wèn)題
python中: 0.3+0.6=0.899999
-
32位浮點(diǎn)數(shù)磨总,超過(guò)2的24次方之后,精度大于1笼沥,運(yùn)算 準(zhǔn)確性不如整數(shù)蚪燕。
2,000,000,000f+1f = 2,000,000,000f
解決方法:Kahan Summation算法