由乙個浮點數引發的思考

2021-09-30 19:22:19 字數 2352 閱讀 3199

下面這段**,輸出值是多少呢?

void main()

在我32位的虛擬機器上,列印輸出值是:data=266270.84

為什麼會出現這種情況呢,難道是計算機出問題了。

當然不是計算機出現了問題,我們從下面幾點來分析**。

首先,我們從浮點數在記憶體中的儲存形式來分析。

大家都知道,資料在記憶體中是以010101這種二進位制的形式儲存的,那浮點數相對整數的儲存又有哪些特殊的地方呢。

按照科學計數法,浮點數在記憶體中分三部分儲存,分別是符號位、指數字、尾數字。

float:單精度浮點數,1位符號位,8位指數字,23位尾數字,總共32位

double:雙精度浮點數,1位符號位,11位指數字,52位尾數字,總共64位。

所以,我們需要把浮點數先轉換成二進位制表示,轉換遵循以下規則

1、先把整數部分和小數部分分別轉換為二進位制形式

2、整數部分轉換為二進位制形式採用「除2取餘,逆序排列」法,即整數部分除以2,取出餘數,商繼續除以2,直到得到0為止,然後將取出的餘數逆序排列

3、小數部分轉換為二進位制形式採用「乘2取整,順序排列」法,即小數部分乘以2,然後取出整數部分,剩下的小數部分繼續乘以2,直到小數部分為零為止。如果永遠不為零,則按照要求保留足夠位數的小數,多餘位需要捨去(0舍1入法),取出的整數部分順序排列。

4、轉換出的二進位制浮點數,進行小數點移位操作,把小數點移到整數字只有一位。

5、計算指數字資料:單精度浮點數指數計算需要做偏移位計算(2^(e-1)-1,e為指數字數),偏移位為127,第4步的小數點移位位數+偏移位=實際指數字資料

例:266270.83

1、整數部分:266270 表示為二進位制  100 0001 0000 0001 1110

2、小數部分:0.83 表示為二進位制  1101  0100  0111…………(總小數字數已超23位)

3、二進位制浮點數:100 0001 0000 0001 1110. 1101  0100  0111…………

4、二進位制浮點數小數點移位操作:總共移位(18位)二進位制表示為---- 1  0010

5、移位後小數表示:1.00 0001 0000 0001 1110  1101  0100  0111…………

6、指數部分計算:0111  1111+1 0010  = 1001 0001

7、浮點數在記憶體中的表示形式:

符號位指數字 

尾數字0 

100 1000 1

000  0010  0000  0011  1101  1010

因為捨去的位為  100  0111…………

按照0舍1入法,捨去的最高位為1,所以最低為需要加1,所以最終在記憶體中表示形式為:

符號位指數字

尾數字0 

100 1000 1

000  0010  0000  0011  1101  1011

8、根據浮點數記憶體中表示形式,進行反推

0       符號位

1000 1    指數字(18)

.000  0010  0000  0011  1101  1011    尾數字 

尾數小數點右移18位

000  0010  0000  0011  110.1  1011

0.   1       1          0       1               1

0.5    0.25      0    0.0625    0.03125

計算出來最終為:266270.84375

列印2位小數,所以最後列印出來就如文章開始列印出的  266270.84

解決辦法:

遇見這種情況,說明單精度浮點數表示已經出現了精度的問題,那我們用雙精度浮點數來表示,即可解決此問題。

簡單的單精度浮點數精度問題判斷

我們知道單精度浮點數小數字數有效為6位,對應二進位制是24位,即要表示一位有效小數,至少佔4位二進位制。那麼,我們就可以根據整數字的二進位制長度和小數精度位數來簡單確定乙個單精度浮點數的精度是否會有問題。

如:266270.83,

整數部分:100 0001 0000 0001 1110   已占用 19-1 = 18位

小數部分:對應的兩位精度小數,需要2*4=8位

合計:整數+小數  18+8=26>24,所以其兩位小數精度會有問題

如:16384.001

整數部分: 100 0000 0000 0000   已占用 15-1 = 14位

小數部分:對應的三位精度小數,需要3*4=12位

合計:整數+小數  14+12=26>24,所以其三位小數精度會有問題

void main()

大家可以試試這段**,結果很驚喜。

由乙個typedef問題引發的思考

同樣,可以像下面這樣隱藏指標語法 typedef char pstr intmystrcmp const pstr p1,const pstr p3 用gnu的gcc和g 編譯器,是會出現警告的,按照順序,const pstr 被解釋為 char const 乙個指向char的指標常量 而事實上,c...

由乙個DAOHelper類引發的思考

這是一篇發牢騷的文章,可以這麼說吧。daohelper究竟有什麼用呢?用我自己的話去理解,daohelper的存在正是敏捷開發的產物,即快速開發。我們究竟能從專案中學到什麼呢?有的人可能會說,從乙個專案中,你可以學到很多東西,比如你可以學習nhibinate,entity framework 等or...

浮點數引發的Canvas繪製血案

今天在android專案開發中遇到乙個比較有趣的奔潰問題,感覺也好久沒有寫文章了,覺得可以跟大家分享一下的。這個問題涉及到浮點數計算 view繪製流程和機制,理清楚後發現問題其實很簡單。1.2.1 下面簡單拆解一下其實現 為什麼僅僅設定了乙個view的visibility就會導致閃退呢?為什麼閃退的...