国产精品免费无遮挡无码永久视频-国产高潮视频在线观看-精品久久国产字幕高潮-国产精品99精品无码视亚

別怪"浮點數"太坑!(C語言版本)

發布時間:2020-5-6 10:53    發布者:嵌入式人生17
嵌入式工程師,別怪"浮點數"太坑!(C語言版本)
1、浮點數如何存儲
    大家在平時的嵌入式軟件開發過程中應該對整形的存儲形式會比較熟悉,因為我們進行底層寄存器的配置大部分都是使用無符號整形進行賦值寫入,然而對于有符號整形的存儲形式你是否已經了解清楚了?對于浮點類型的數據的存儲呢?好吧,今天這篇文章主要是對浮點類型數據進行講解,其他相關大家可以查閱相關資料閱讀學習,作者后續也會整理發布。
1)浮點存儲形式
    對于語法等知識一般都是建立在一定的規范之上的,不然不利于技術的兼容統一發展,但是在不同的領域由于有著不同的需求,可能遵循的規范有所差異,對于浮點數的規范目前大部分系統都采用的是IEEE 754標準。我們這里4字節單精度浮點類型為例子為大家講解一下浮點數的存儲形式其他浮點數存儲僅僅每部分數據大小不同)
file:///C:\Users\Administrator.WIN-STED6B9V5UI\AppData\Local\Temp\ksohtml3492\wps19.jpg
    對于浮點數的存儲形式可以用2進制科學計數法表示:
    (符號:+/-1.(二進制尾數)*2^(指數=實際指數+偏移量)
    對于這幾個名詞不是特別好解釋,結合實際轉化過程會更加好理解這里以float型浮點數:4.25為例子,如下轉化示意圖)
file:///C:\Users\Administrator.WIN-STED6B9V5UI\AppData\Local\Temp\ksohtml3492\wps20.png
·
對于小數部分的二進制表示采用除二反取的方法獲得;
·
·
23bit的尾數部分前面0001即為科學二進制的小數點后面部分,其他bit0填充;
·
·
指數部分會添加一個偏移量127,這個僅僅是對于float類型;對于其他浮點類型由于表示的數據范圍不同偏移也不同,比如double需要+1023的偏移。
·
·
由于我們舉例4.25 > 1,那么我們實際指數 > 0;如果我們的浮點是0.025,這個時候實際指數為負數,大家可以嘗試編碼轉化。
·
2)浮點精度問題
    我們通過上面浮點數的存儲方式可以知道8bit的指數最大可以表示255,最大值的指數就是255 - 127 = 1282^128 = 3.402..e+38;(確實非常大!)
    如果用我們的4byte無符號整形表示最大數據為2^32,看起來遠遠小于浮點表示;不過大家是否想過一個問題,根據數據二進制一一對應原則都是4byte的表示方法為什么有這么大差異,難道浮點數憑空創造了更多的數據嗎?
    非也非也,指數部分代表著浮點數的范圍,尾數部分代表著浮點數的精度;我們從尾數的角度來看,浮點的二進制科學計數法小數點前始終是最高位,這也就意味指數越大,尾數部分所表示的數值越大,其精度越差。所以floatuint表示的數據個數都是一樣的,整形表示的數據是均勻的,而浮點表示的數據在數值比較小的時候精度比較高,而數值比較大的時候就比較低了,同時也說明浮點表示僅僅是一種近似的表示方法,不能精確的表示數值,所以有時候大家在編程的過程中明明向float類型變量賦值了一個準確的數據,仿真一看數據成了一個近似值。
3)浮點與"=="
    這個問題也是大家經常討論的,不過還是需要具體情況具體分析,到底浮點數能不能用等于號來進行判斷呢?首先我們看看什么叫相等,相等就是一模一樣,對于計算機而言就是二進制相等,否則我們只能叫近似。前面我們了解到了浮點的存儲形式,如果兩個浮點的三個部分都是相等的(符號位+指數+尾數),那么這個時候這兩個浮點數就是絕對的相等,如果不能達到完全相等就只能使用近似判斷相等,比如我們常用下面的方式來表示:
/***************************************
*Author:(公眾號:最后一個bug)
****************************************/
#define FLOAT_EPS (0.000001) //根據需求
#define Float_Equ(a, b) ((fabs((a)-(b)))<(FLOAT_EPS))
    不過對于浮點數相等大家盡量還是減少使用,較多浮點運算控制器都會有不同的處理方式,比如說擴展精度、截取尾數等等,對于代碼的可移植性減弱。
  
2、玩轉浮點數
    前面為大家詳細的介紹了浮點數的理論知識,大家好好溫習一下,這里再為大家分享一下平時用得比較多的浮點數案例,特別是在通信中傳輸浮點數據,數據的組拼容易出現的一些小插曲,同時也是初學者容易忽略的知識點:
(代碼走起!
#include
#include

typedef union _tag_FloatConvert
{
    unsigned char byte[4];
    float Result;
}uFloatConvert;
/*****************************************
* Fuction: main
* Author 公眾號:最后一個bug)
*****************************************/
int main(int argc, char *argv[]) {
    uFloatConvert unFloatConvert;
    float fVal   = 4.25;
    int   iVal   = 0x40880000;
    float *pfVal = NULL;
    int   *pIVal = NULL;

    //1)初學組拼數據經常的錯誤
    fVal  = (float)iVal;
    printf("*fVal = %.3f\n",fVal);
    printf("iVal = %d\n",iVal);
    //2) 正確組拼數據
    pfVal = (float*)(&iVal);
    printf("*pfVal = %.3f\n",*pfVal);

    //3)采用共聯體進行數據轉化(方便)--大家以后可以封裝成函數
    unFloatConvert.byte[0] = 0x00;
    unFloatConvert.byte[1] = 0x00;
    unFloatConvert.byte[2] = 0x88;
    unFloatConvert.byte[3] = 0x40;
    printf("unFloatConvert.Result = %.3f\n",unFloatConvert.Result);
    printf("公眾號:最后一個bug\n");
    return 0;
}
    運行結果如下:
file:///C:\Users\Administrator.WIN-STED6B9V5UI\AppData\Local\Temp\ksohtml3492\wps21.png
    解析一下:
·
1 ) 很多初學者做浮點通信字節接收把接收到的數據組織成整形然后直接強制類型轉化為浮點,然而這樣并不能轉化為原始的浮點數,從上面的運行結果也可以看出來;然而我們采用float指針來進行如上轉換卻得到了正確結果,具體的原因大家通過第一個和第二個打印結果應該就明白了。
·
·
2 ) 同時作者這里給出了平時用來轉化浮點的共聯體方法,該方法使用起來比較靈活方便,主要的原理是共聯體共用內存空間,不過要注意大小端問題,相關知識可以看我的往期文章。
·

本文地址:http://www.4huy16.com/thread-587433-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • “芯”光璀璨,鵬城共賞——2025 Microchip中國技術精英年會深圳站回顧
  • 技術熱潮席卷三城,2025 Microchip中國技術精英年會圓滿收官!
  • 常見深度學習模型介紹及應用培訓教程
  • Microchip第22屆中國技術精英年會上海首站開幕
  • 貿澤電子(Mouser)專區
關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表