c51中的浮點數儲存方式
--n年前曾在c51bbs論壇中發布過
float 浮點形,它是符合ieee-754標準的單精度浮點形資料,在十進位制中具有7位有效數字。float型據占用四個位元組(32位二進位制數),在記憶體中的存放格式如下:
位元組位址(由低到高)0 1 2 3
浮點數內容 mmmmmmmm mmmmmmmm e mmmmmmm s eeeeeee
其中,s為符號位,存放在最高位元組的最高位。「1」表示負,「0」表示正。e為階碼,占用8位二進位制數,存放在高兩個位元組中。注意,階碼e值是以2為底的指數再加上偏移量127,這樣處理的目的是為了避免出現負的階碼值,而指數是可正可負的。階碼e的正常取值範圍是1~254,從而實際指數的取值範圍為-126-127。m為尾數的小數部分,用23位二進位制數表示,存放在低三個位元組中。尾數的整數部分永遠為1,因此不予儲存,但它是隱含的。小數點位於隱含的整數字「1」的後面。
例如浮點數124.75 = 42f98000h 在記憶體中的存放格式為:
位元組位址 +0 +1 +2 +3
浮點數內容 00000000 10000000 1 1111001 0 1000010
124.75d=1111100.11b=1.11110011*2e6
階碼=6d+127d=133d=10000101b
符號位=0
參考示例程式一:
typedef union float;
main()
參考示例程式二:
main()
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 ;
這個union包含乙個float和乙個unsigned long以便執行浮點數**算並響應ieee錯誤
狀態。
尾數為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,切記!
計算機使用二進位制數計算,能有效利用電子器件高速開關的特性,而人習慣於十進位制數
表示,二進位制和十進位制沒有方便的轉換方法,只能通過大量計算實現,浮點數的十進位制科學
記數法顯示尤其需要大量的運算,可見,顯示乙個浮點數要經過若干次浮點運算,沒有必要
就不要顯示,否則,花在顯示上的時間比計算的耗時都要多得多。
浮點數表示
之前的一些工作當中碰到了很多有關浮點數的問題,比如浮點數的表達範圍 表達精度 浮點數的儲存方式 浮點數的強制型別轉換等等,因此感覺有必要系統了解一下有關浮點數的問題。浮點數是一種公式化的表達方式,用來近似表示實數,並且可以在表達範圍和表示精度之間進行權衡 因此被稱為浮點數 浮點數通常被表示為 n m...
IEEE的浮點數表示
ieee浮點標準用v 1 s m 2 e 由符號,尾數,階碼表示 32位單精度 單精度二進位制小數,使用32位儲存。1 8 23 位長 s exp fraction 31 30 23 22 0 位編號 從右邊開始為0 偏正值 127 64位雙精度 雙精度 二進位制小數,使用64位儲存。1 11 52...
浮點數的表示方法
把乙個數的有效數字和數的範圍在計算機的乙個儲存單元中分別予以表示。這種把數的範圍和精度分別表示的方法,相當於數的小數點位置隨比例因子的不同而在一定範圍內可以自由浮動,所以稱為浮點表示法。在計算機中乙個任意二進位制數n可以寫成 n 2 e.m 其中m稱為浮點數的尾數,是乙個純小數。e是比例因子的指數,...