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、浮點數有舍入誤差,運算需要嚴格注意次序,避免精度下降。