日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > > 嵌入式微處理器
[導(dǎo)讀]? ? 本篇文章主要解決的問題是C語言整形與浮點型轉(zhuǎn)化過程中的精度損失從而容易產(chǎn)生bug,對于浮點和整形的相關(guān)內(nèi)容大家可以參考下面兩篇文章<【重磅】“整形數(shù)”還真沒那么簡單(C語言版)>、<【典藏】別怪"浮點數(shù)"太坑(C語言版本)>,這里就不再贅敘了。 1 整



    本篇文章主要解決的問題是C語言整形與浮點型轉(zhuǎn)化過程中的精度損失從而容易產(chǎn)生bug,對于浮點和整形的相關(guān)內(nèi)容大家可以參考下面兩篇文章<【重磅】“整形數(shù)”還真沒那么簡單(C語言版)>、<【典藏】別怪"浮點數(shù)"太坑(C語言版本)>,這里就不再贅敘了。


1

整形與浮點轉(zhuǎn)化的精度損失
參考小程序:
 1#include <stdio.h>
2#include <stdlib.h>
3
4/*************************************
5 * Fuction:精度損失 
6 * Author : (公眾號:最后一個bug) 
7 ************************************/
 
8 int main(int argc, char *argv[]) {
9    float fVal1 = 0;
10    int   sVal1 = 60012502;
11    int   sVal2 = 60012501;
12
13    printf("sizeof(int) = %d\n",sizeof(int));
14    printf("sizeof(float) = %d\n",sizeof(float));
15
16    fVal1 = (float) sVal1;
17    printf("fVal1 = %f\n",fVal1);
18
19    fVal1 = (float) sVal2;
20    printf("fVal1 = %f\n",fVal1);
21
22
23    sVal1 = (int) fVal1;
24    printf("sVal1 = %d\n",sVal1);
25
26    sVal2 = (int) fVal1;
27    printf("sVal2 = %d\n",sVal2);
28
29    if(sVal1 == sVal2)
30    {
31        printf("sVal1 == sVal2\n");     
32    }
33    else 
34    {
35        printf("sVal1 != sVal2\n"); 
36    }
37
38    printf("公眾號:最后一個bug\n"); 
39
40    return 0;
41}
運行結(jié)果:

分析一下:
  • 我只想說真的牛,轉(zhuǎn)來轉(zhuǎn)去竟然使得兩個不一樣的數(shù)相等了,所以大家在平時的項目中進(jìn)行強制類型轉(zhuǎn)化可要慎重考慮下了。

  • 其發(fā)生該情況的主要原因是由于4字節(jié)float類型變量不能完全覆蓋int類型的所有類型數(shù)值,所以在進(jìn)行強制類型轉(zhuǎn)化的過程中會產(chǎn)生精度上的損失,這樣大家稍不留意就會有一些不必要的麻煩。

2

沒必要強制轉(zhuǎn)化的地方

    大家對數(shù)據(jù)進(jìn)行強制類型轉(zhuǎn)化很大部分都是為了方便計算,比如通過AD采樣獲得的數(shù)據(jù)都是整形的數(shù)據(jù),通過比例因子處理以后成為了浮點數(shù)據(jù),然后通過浮點進(jìn)行計算實在是再方便不過了。

    對于上面這種強制類型轉(zhuǎn)化情景是值得考慮的,可是對于下面的場景就沒有必要了,反而容易出現(xiàn)問題。



    對于上面這種處理情景,估計很多小伙伴就直接通過整形接受到數(shù)據(jù),然后強制類型轉(zhuǎn)化為了浮點類型進(jìn)行保存,當(dāng)需要使用到該參數(shù)的時候,又通過把該浮點存儲保存的值強制類型轉(zhuǎn)化為整形,最后再進(jìn)行整形參數(shù)的相關(guān)處理。

    經(jīng)過這樣整形-->浮點-->整形的處理,如果你拿著最后的整形進(jìn)行數(shù)據(jù)判斷,就很大概率上會存在類似于前面的Demo程序那樣存在bug。

   那么有一些小伙伴該問了,為什么不用整形存儲呢 ? 用整形存儲不就沒這個問題了嗎 ?當(dāng)你真正進(jìn)入工作崗位,可能某一天一個同事離職,把一堆攤子丟給你了,然而里面的數(shù)據(jù)結(jié)構(gòu)等等處理,不是不想動,而是不敢動,往往新接手的代碼把控能力有有限,可能不小心的參數(shù)配置都會導(dǎo)致程序奔潰,還真不敢大動作?所以還是技巧性的填好坑,等待下一次重構(gòu)的機會。

3

處理小技巧

    其實對于內(nèi)存上所保存的數(shù)據(jù)是沒有具體類型的,所謂數(shù)據(jù)類型僅僅只是以怎樣一種方式進(jìn)行數(shù)據(jù)的訪問罷了,我們通過指針來進(jìn)行訪問就很好的說明了這個問題,例如int *ptr,表示ptr所指向的地址以int類型進(jìn)行訪問,如果把ptr改為float類型即float *ptr,其便以float類型來訪問地址所對應(yīng)的內(nèi)存。

    既然像第二小節(jié)說的float類型的參數(shù)保存區(qū)無法修改了,那么我們就想辦法直接繞過float類型來進(jìn)行數(shù)據(jù)訪問。

參考demo:
 1#include <stdio.h>
2#include <stdlib.h>
3
4/*************************************
5 * Fuction: 兩個宏--可以繼續(xù)擴(kuò)展 
6 * Author : (公眾號:最后一個bug) 
7 ************************************/
 
8#define SET_INT_VAL(addr,val)  *((int*)(&addr)) = val
9#define SET_GET_VAL(addr)      *((int*)(&addr))
10
11/*************************************
12 * Fuction: 改善小技巧 
13 * Author : (公眾號:最后一個bug) 
14 ************************************/
 
15 int main(int argc, char *argv[]) {
16    float fVal1 = 0;
17    int   sVal1 = 60012502;
18
19    printf("sizeof(int)   = %d\n",sizeof(int));
20    printf("sizeof(float) = %d\n",sizeof(float));
21
22    //接受整形數(shù)據(jù)到float數(shù)據(jù)內(nèi)存 
23    SET_INT_VAL(fVal1,sVal1); 
24
25    //float數(shù)據(jù)內(nèi)存獲得整形數(shù)據(jù) 
26    printf("SET_GET_VAL(fVal1) = %d\n",SET_GET_VAL(fVal1)); 
27    printf("            sVal1  = %d\n",sVal1); 
28
29    printf("公眾號:最后一個bug\n"); 
30
31    return 0;
32}
運行結(jié)果:

分析一下:
  • Demo中通過兩個宏進(jìn)行地址的類型處理轉(zhuǎn)化,對float內(nèi)存進(jìn)行直接訪問來保存整形數(shù)據(jù),同樣后面通過地址的直接訪問來獲得整形數(shù)據(jù),這樣就可以繞開float類型的處理問題。

  • 同時大家也要注意其本地類型占用字節(jié)大小(float)需>=所要轉(zhuǎn)化的類型占用字節(jié)大小(int),否則會造成數(shù)據(jù)的篡改,這樣就會造成更多麻煩。

  • 其實這里僅僅只用float進(jìn)行存儲參數(shù)的設(shè)計,原本就存在設(shè)計上的缺陷,可以通過共聯(lián)體,或者無類型內(nèi)存設(shè)計方案進(jìn)行處理,這樣就不會出現(xiàn)類似的問題了。

 

4、最后小結(jié)

    今天主要是跟大家分享了一個小案例,大家好好理解下,C語言雖然語法不多,不過想要寫出好的C代碼并非易事,需要多練多悟!作者也會慢慢回顧這些年的編程經(jīng)驗并分享給大家。


免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

嵌入式ARM

掃描二維碼,關(guān)注更多精彩內(nèi)容

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉