久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計實(shí)例 >> 瀏覽文章

浮點(diǎn)型數(shù)據(jù)存儲方式分析

作者:huqin   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時間:2014年03月13日   【字體:

  筆試面試的過程中難免會遇到很多自己不清楚或者是當(dāng)時不清楚的問題,關(guān)于浮點(diǎn)型數(shù)據(jù)的問題我認(rèn)為是比較難的問題啦,如果不清楚浮點(diǎn)型存儲問題,回答問題只有猜結(jié)果了。

   
    在面試的過程中一般面試官也很少問關(guān)于浮點(diǎn)數(shù)的問題,因?yàn)楦↑c(diǎn)數(shù)對于很多的處理器是不支持的,對于上層應(yīng)用的程序員而言,存儲類型的問題都會考慮,但是對于嵌入式程序員掌握內(nèi)存的分配情況是必須的,只有這樣才能把握基本的操作,關(guān)于浮點(diǎn)型數(shù)據(jù),在C語言中存在兩種類型的浮點(diǎn)型,其中一種是單精度的浮點(diǎn)型 (float)、雙精度的浮點(diǎn)型(double)。浮點(diǎn)型數(shù)據(jù)和一般的整形數(shù)據(jù)具有較大的差別,具體的差別就是浮點(diǎn)型數(shù)據(jù)是一個近似值,并不是一個準(zhǔn)確的值,這也就是為什么在比較浮點(diǎn)型數(shù)據(jù)的大小時不能采用直接等于的方式進(jìn)行比較,因?yàn)楦↑c(diǎn)型只是一個近似值,也就是一個值可能表示一個范圍區(qū)間,這樣的表達(dá)方式就使得對浮點(diǎn)型采用相等的判斷方法進(jìn)行判斷可能不合理,只有通過比較一個數(shù)是否在這個小的范圍內(nèi),在這個小的范圍內(nèi)說明這個數(shù)可以表述這個范圍內(nèi)的數(shù)據(jù)。因此在計算值比較兩個浮點(diǎn)數(shù)變量不能通過做差是否等于零來判斷。而只能通過如下的方式判斷:
 
  1. const float ESPSION = 0.000001;
  2. if((x-y)>=-ESPSION && (x-y)<= ESPSION)
    這種實(shí)現(xiàn)方式是基本的比較方式,這種判讀方法剛好就是判斷變量是否處于一個范圍內(nèi),這里的范圍是-0.000001<x<0.000001。
   記得在網(wǎng)上關(guān)于浮點(diǎn)型的一道題目如下:

 

 

 

 
    typedef union test
    {
        float a;
        int i;
        char c[4];
    }Test;
    int main()
    {
        Test t;
        t.a = 5.0;
        printf("%f\n",t.a)
        printf("%d\n",t.i);
        printf("%c,%c,%c,%c\n",t.c[3],t.c[2],t.c[1],t.c[0]);
        return 0;
    }
    這個題剛開始看的時候我并不知道其中有什么問題,我認(rèn)為就是簡單的數(shù)值強(qiáng)制類型轉(zhuǎn)換,但是后面我發(fā)現(xiàn)并不是強(qiáng)制類型轉(zhuǎn)換,這個題只有搞清楚了數(shù)據(jù)的存儲方式才能真正的清楚輸出的結(jié)果。
    其實(shí)關(guān)于數(shù)據(jù)類型的存儲方式問題的題目類型很多,其中比較常見的有:1、存儲空間大小問題,即字節(jié)對齊問題,這種問題一般要求我們對基本類型了解其中的基本原理,相對來說比較簡單。2、字符串的長度問題,這種問題主要是通過sizeof,strlen這兩個不同的函數(shù)來比較。3、還有一類問題就是采用 printf函數(shù)實(shí)現(xiàn)數(shù)據(jù)類型的轉(zhuǎn)換問題。這種轉(zhuǎn)化問題是在printf的格式中體現(xiàn)出來的,是各種關(guān)于內(nèi)存分布最容易失誤的地方,為什么說最容易失誤呢,因?yàn)椴煌膮?shù)就有可能產(chǎn)生不一樣的輸出結(jié)果,說白了這種題很容易出錯是因?yàn)槲覀兒苌僮⒁膺@些問題。
   
    上面的這個題返回值非常的特殊,為什么會特殊呢?我就通過浮點(diǎn)數(shù)的基本存儲方式來說明。在32位系統(tǒng)中,float類型占有4個bytes,double 則占有8個bytes。對于整形數(shù)據(jù)而言,我們很容易就知道數(shù)據(jù)是順序存儲的,雖然有大小端之分,但是基本的準(zhǔn)則我們認(rèn)為是按照順序存儲的。但是 float和double型卻是比較特殊的數(shù)據(jù)類型,因?yàn)檫@兩種數(shù)據(jù)類型并不是按照整形數(shù)據(jù)的順序存儲方式進(jìn)行存儲的,而是按照一定的標(biāo)志IEEE來實(shí)現(xiàn)的,都有各自的標(biāo)志編碼方式:
 
    浮點(diǎn)型變量在計算機(jī)內(nèi)存中占用4字節(jié)(Byte,32-bit。遵循IEEE-754格式標(biāo)準(zhǔn)。一個浮點(diǎn)數(shù)由2部分組成:底數(shù)m 指數(shù)e
                          ±mantissa × 2^exponent
(注意,公式中的mantissa exponent使用二進(jìn)制表示)
                     (具體可參看深入理解計算機(jī)系統(tǒng))
 
    底數(shù)部分 使用2進(jìn)制數(shù)來表示此浮點(diǎn)數(shù)的實(shí)際值。
    指數(shù)部分 占用8-bit的二進(jìn)制數(shù),可表示數(shù)值范圍為0255。但是指數(shù)應(yīng)可正可負(fù),所以IEEE規(guī)定,此處算出的次方(即是來自內(nèi)存存儲的內(nèi)容,存儲指數(shù))須減去127才是真正的指數(shù)(實(shí)際的指數(shù),如12.5轉(zhuǎn)換為二進(jìn)制為:1100.100=1.100100*23, 3即為實(shí)際指數(shù))。所以float的指數(shù)可從 -126128.
        底數(shù)部分實(shí)際是占用24-bit的一個值,由于其最高位始終為1,所以最高位省去不存儲,在存儲中只有23-bit到目前為止,底數(shù)部分23位加上指數(shù)部分8使用31位。那么前面說過,float是占用4個字節(jié)即32-bit, 那么還有一位是干嘛用的呢?  還有一位,其實(shí)就是4字節(jié)中的最高位,用來指示浮點(diǎn)數(shù)的正負(fù),當(dāng)最高位是1時,為負(fù)數(shù),最高位是0時,為正數(shù)。
 
也就是說我們可以認(rèn)為float在小端CPU的編碼方式應(yīng)該是:
31<-------------------------------------------------0
S(1bit)| E(8bits)|           M(23bits)              |
 
即:
-----------------------------------------------------
ADDR0+3         ADDR0+2        ADDR0+1         ADDR0
SEEEEEEE        EMMMMMMM       MMMMMMMM     MMMMMMMM
-----------------------------------------------------
      S: 表示浮點(diǎn)數(shù)正負(fù),1為負(fù)數(shù),0為正數(shù)。
      E: 指數(shù)加上127后的值的二進(jìn)制數(shù)
      M: 24-bit的底數(shù)(只存儲23-bit
需要注意,浮點(diǎn)數(shù)0時,指數(shù)和底數(shù)都為0,但此前的公式不成立。因?yàn)?/span>20次方為1,所以,0是個特例。當(dāng)然,這個特例也不用認(rèn)為去干擾,編譯器會自動去識別。
 
   這樣我們就可以知道前面這個題中輸出的結(jié)果啦,從上面的分析可以知道一個float型的數(shù)的基本存儲方式,按照上面的實(shí)現(xiàn)可以知道5.0的存儲方式為如下的形式:
                          01000000101000000000000000000000
   從上面的這個存儲形式我們可以得到基本的整形數(shù)值時0x40A00000。進(jìn)而也就知道了4個bytes中的數(shù)值大小。
  
   這是充分利用了聯(lián)合體的共享內(nèi)存特性,我們改變程序如下所示:
 
    #include<stdio.h>
    typedef union test
    {
        float a;
        int i;
        char c[4];
    }Test;
    int main()
    {
        Test t;
        t.a = 5.0;
        printf("%f\n",t.a);
        printf("%d\n",t.i);
        printf("%c,%c,%c,%c\n",t.c[3],t.c[2],t.c[1],t.c[0]);
        t.i = 65;
        printf("%f\n",t.a);
        printf("%d\n",t.i);
        printf("%c,%c,%c,%c\n",t.c[3],t.c[2],t.c[1],t.c[0]);
        return 0;
    }
 
     根據(jù)上面的分析,可以比較方便的計算出結(jié)果如下所示:
    當(dāng)然這只是我在X86系統(tǒng)中的輸出,在大端系統(tǒng)中會是什么結(jié)果我不得而知,具體的要參看IEEE標(biāo)準(zhǔn)。
    float類型的數(shù)據(jù)是比較復(fù)雜的問題,我將在后面認(rèn)真研究,爭取早日解決各種問題。
關(guān)閉窗口

相關(guān)文章

主站蜘蛛池模板: 欧美日韩电影一区 | 欧美性一区二区三区 | 我想看一级黄色毛片 | 日韩av中文| 国产一区二区三区精品久久久 | 亚洲网站免费看 | 婷婷久久一区 | www.国产.com| 国产一区二区三区在线 | 欧美xxxx做受欧美 | 一本色道久久综合亚洲精品高清 | 欧美精品一区二区在线观看 | 中文在线亚洲 | 亚洲国产激情 | 精品一二区 | 久久中文字幕一区 | 精品丝袜在线 | 国产精品免费大片 | 久久青草av | 午夜成人免费视频 | 国产高清一区二区 | 久久艹免费视频 | 国产一区在线免费观看视频 | 国产中文 | 在线伊人网 | 毛片一区二区三区 | 神马影院一区二区三区 | 日韩精品一区二区三区 | 久久精品国产清自在天天线 | 在线免费观看黄色av | 黄色毛片黄色毛片 | 天天澡天天狠天天天做 | 欧美日韩不卡合集视频 | 天天久久 | 欧美日韩一区在线 | 香蕉视频黄色 | 国产精品久久久久久婷婷天堂 | 成人在线视频一区 | 中文字幕一区二区在线观看 | 国产区第一页 | 精品国产乱码一区二区三 |