C51浮點數顯示、浮點數表示方法


C51里用4字節存儲一個浮點數,格式遵循IEEE-754標准(詳見c51.pdf第179頁說明)。一 
個浮點數用兩個部分表示,尾數和2的冪,尾數代表浮點上的實際二進制數,2的冪代表指 
數,指數的保存形式是一個0到255的8位值,指數的實際值是保存值(0到255)減去127,一個 
范圍在-127到+128之間的值,尾數是一個24位值(代表大約7個十進制數),最高位MSB通常是 
1,因此不保存。一個符號位表示浮點數是正或負。 
浮點數保存的字節格式如下: 
地址        +0          +1           +2           +3 
內容    SEEE EEEE   EMMM MMMM    MMMM MMMM    MMMM MMMM 
這里 
S 代表符號位,1是負,0是正 
E 偏移127的冪,二進制階碼=(EEEEEEEE)-127。 
M 24位的尾數保存在23位中,只存儲23位,最高位固定為1。此方法用最較少的位數實現了 
較高的有效位數,提高了精度。 
零是一個特定值,冪是0 尾數也是0。 
浮點數-12.5作為一個十六進制數0xC1480000保存在存儲區中,這個值如下: 
地址 +0     +1     +2     +3 
內容0xC1   0x48   0x00   0x00 
浮點數和十六進制等效保存值之間的轉換相當簡單。下面的例子說明上面的值-12.5如何轉 
換。 
浮點保存值不是一個直接的格式,要轉換為一個浮點數,位必須按上面的浮點數保存格式表 
所列的那樣分開,例如: 
地址       +0           +1            +2            +3 
格式   SEEE EEEE    EMMM MMMM     MMMM MMMM     MMMM MMMM 
二進制  11000001     01001000      00000000      00000000 
十六進制   C1           48            00            00 
從這個例子可以得到下面的信息: 
  符號位是1 表示一個負數 
  冪是二進制10000010或十進制130,130減去127是3,就是實際的冪。 
  尾數是后面的二進制數10010000000000000000000 

在尾數的左邊有一個省略的小數點和1,這個1在浮點數的保存中經常省略,加上一個1和小數 
點到尾數的開頭,得到尾數值如下: 
1.10010000000000000000000 
接着,根據指數調整尾數.一個負的指數向左移動小數點.一個正的指數向右移動小數點.因為 
指數是3,尾數調整如下: 
1100.10000000000000000000 
結果是一個二進制浮點數,小數點左邊的二進制數代表所處位置的2的冪,例如:1100表示 
(1*2^3)+(1*2^2)+(0*2^1)+(0*2^0)=12。 
小數點的右邊也代表所處位置的2的冪,只是冪是負的。例如:.100...表示(1*2^(-1))+ 
(0*2^(-2))+(0*2^(-2))...=0.5。 
這些值的和是12.5。因為設置的符號位表示這數是負的,因此十六進制值0xC1480000表示- 
12.5。 
浮點數錯誤信息 
    8051沒有包含捕獲浮點數錯誤的中斷向量,因此,你的軟件必須正確響應這些錯誤情 
況。 
    除了正常的浮點數值,還包含二進制錯誤值。這些值被定義為IEEE標准的一部分並用在 
正常浮點數操作過程中發生錯誤的時候。你的代碼應該在每一次浮點操作完成后檢查可能出 
現的錯誤。 
        名稱        值       含義 
        NaN     0xFFFFFFF   不是一個數 
        +INF    0x7F80000   正無窮(正溢出) 
        -INF    0xFF80000   負無窮(負溢出) 
    你可以使用如下的聯合體(union)存儲浮點數。 
    union f { 
      float          f;  //浮點值 
      unsigned long ul;  //無符號長整數 
    }; 
    這個union包含一個float和一個unsigned long以便執行浮點數**算並響應IEEE錯誤 
狀態。 
     
    以上是KEIL在線幫助的中譯文,下面我們討論如何顯示浮點數。 
     
    尾數為24bit,最高可表達的整數值為2^24-1=16777215,也就是說,小於等於16777215 
的整數可以被精確顯示。這決定了十進制浮點數的有效位數為7位,10^7<16777215<10^8, 
10的7次方以內的數小於16777215,可以精確表示。使用科學記數法時,整數部分占1位,所 
以小數部分最大占7-1=6位,即最大有6位十進制精度。 
    長整形數和浮點數都占4字節,但表示范圍差別很大。浮點數的范圍為+-1.175494E-38 
到+-3.402823E+38,無符號長整形數范圍為0到4294967295。顯示浮點數要用到長整形數保 
存數據,可他們范圍差這么多,怎么辦呢? 
    仔細觀察十進制浮點數的顯示,有一個尾數和一個階碼,由上面論證可知32位IEEE-754 
浮點數最大有效數字為7位十進制數,超出此范圍的數字有截斷誤差,不必理會,因此,浮 
點數尾數能夠放在長整形數里保存。階碼為-38到38,一個char型變量就可以保存。 
    綜上所述,以10^7的最大跨度為窗口(小於10^7也可以,如:10,100...10000等,但決 
不能大於它,那樣會超出精度范圍),定位浮點數的量級,然后取出7位尾數的整數值存於長 
整形數里,再調整階碼,就可以精確顯示此浮點數。 
    量級尺度如下: 
      (-38)-(-35)-(-28)-(-21)-(-14)-(-7)-(0)-(7)-(14)-(21)-(28)-(35)-(38) 
    請嚴格按照KEIL手冊給出的浮點數范圍顯示,因為數值空間沒有完全使用,有些值用於 
錯誤指示和表示正負無窮。小於1.175494E-38的數仍可以顯示一些,但最好不用,以免出 
錯。我采用直接判斷的方法,剔除此種情況。 
    在計算機里結合律不成立,(a*b)*c!=a*(b*c),原則是先讓計算結果值動態范圍小的兩 
個數運算,請注意程序里的寫法。 
    注:(1E38/b)*1E6不要寫成1E44/b,因為無法在32位浮點數里保存1E44,切記! 
    計算機使用二進制數計算,能有效利用電子器件高速開關的特性,而人習慣於十進制數 
表示,二進制和十進制沒有方便的轉換方法,只能通過大量計算實現,浮點數的十進制科學 
記數法顯示尤其需要大量的運算,可見,顯示一個浮點數要經過若干次浮點運算,沒有必要 
就不要顯示,否則,花在顯示上的時間比計算的耗時都要多得多。

 

轉發自:https://blog.csdn.net/liang890319/article/details/12558913?locationNum=15&fps=1

 

筆記:

1、浮點數同樣有存儲范圍的問題,注意冪次。

2、在一定的誤差范圍內,即可認為兩個浮點數相等。

2、浮點數有舍入誤差,運算需要嚴格注意次序,避免精度下降。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM