亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        C語(yǔ)言中浮點(diǎn)數(shù)精度問(wèn)題分析

        2015-02-13 01:28:39周冠方
        關(guān)鍵詞:程序

        周冠方

        (鄖陽(yáng)師范高等專(zhuān)科學(xué)校組織人事部,湖北十堰420000)

        C語(yǔ)言中浮點(diǎn)數(shù)精度問(wèn)題分析

        周冠方

        (鄖陽(yáng)師范高等專(zhuān)科學(xué)校組織人事部,湖北十堰420000)

        通過(guò)實(shí)例直觀地描述了C語(yǔ)言中由于計(jì)算機(jī)存儲(chǔ)數(shù)據(jù)方式的不同而造成的數(shù)據(jù)誤差,并對(duì)誤差產(chǎn)生的原因進(jìn)行了分析,解讀出C語(yǔ)言中浮點(diǎn)型數(shù)據(jù)的不同存儲(chǔ)方式,最后給出幾點(diǎn)建議。

        C語(yǔ)言;數(shù)據(jù)精度;浮點(diǎn)型數(shù)據(jù);相對(duì)誤差

        1 引言

        C語(yǔ)言程序設(shè)計(jì)的基本數(shù)據(jù)類(lèi)型包含整型和浮點(diǎn)型兩類(lèi)。在計(jì)算機(jī)中,實(shí)數(shù)特別是小數(shù)形式表示的數(shù)都是以浮點(diǎn)型數(shù)據(jù)來(lái)進(jìn)行存儲(chǔ)的。但是對(duì)于浮點(diǎn)型的數(shù)據(jù),在進(jìn)行各種運(yùn)算時(shí),因?yàn)橛?jì)算機(jī)的二進(jìn)制存儲(chǔ)特性,會(huì)導(dǎo)致出現(xiàn)精度丟失的現(xiàn)象。這種現(xiàn)象直接影響到程序結(jié)果的準(zhǔn)確性和可靠性。

        2 C語(yǔ)言中數(shù)據(jù)類(lèi)型轉(zhuǎn)換帶來(lái)的影響

        先來(lái)看一個(gè)簡(jiǎn)單的例子:需要求解A=4/5的值,這個(gè)結(jié)果很簡(jiǎn)單,A=0.8。而在C語(yǔ)言中,我們寫(xiě)出它的計(jì)算程序:

        Main()

        Float A;

        A=4/5;

        Printf(“A=%f\n”,A);

        Return 0;

        結(jié)果:A=0.000000

        從算法的角度來(lái)看這個(gè)程序沒(méi)有問(wèn)題,但是最終運(yùn)行的結(jié)果卻和我們的理論值完全不相符。這是為什么呢?

        分析:在此程序中兩操作數(shù)4和5均為整型,運(yùn)算結(jié)果應(yīng)該為0.8,但是在C語(yǔ)言程序編寫(xiě)中有這樣一個(gè)規(guī)則,C語(yǔ)言中計(jì)算的源數(shù)據(jù)為整形數(shù)據(jù),最終輸出結(jié)果也應(yīng)該為整形數(shù)據(jù)?!?/5”的結(jié)果0.8在C語(yǔ)言中會(huì)被轉(zhuǎn)換后得到一個(gè)int型的中間變量,它的值等于“4/5”的整數(shù)部分,其小數(shù)部分則被進(jìn)行截尾操作,即舍棄整個(gè)小數(shù)部分,最終存儲(chǔ)值為0。程序?qū)⑦@個(gè)整型的運(yùn)算結(jié)果賦給A這個(gè)float型變量,將其強(qiáng)制轉(zhuǎn)換為float型輸出,所以最終運(yùn)算結(jié)果成了A=0.000000。

        如果我們需要去確保最終輸出結(jié)果的正確性,我們就必須在計(jì)算的過(guò)程中就將中間的操作數(shù)據(jù)更改為浮點(diǎn)型數(shù)據(jù),來(lái)確保最終結(jié)果數(shù)據(jù)和中間操作數(shù)據(jù)的數(shù)據(jù)類(lèi)型的同質(zhì)性。

        此例有兩種簡(jiǎn)單的解決辦法:

        1)將“A=4/5”改成“A=4.0/5.0”;

        2)將“A=4/5”改成“A=(float)4/5”。

        即可得出最終正確的值A(chǔ)=0.800000。因此,如果我們遇到因?yàn)镃語(yǔ)言程序設(shè)計(jì)中,不同數(shù)據(jù)類(lèi)型之間的計(jì)算問(wèn)題時(shí),我們必須規(guī)定明確的數(shù)據(jù)類(lèi)型,并且在算法編寫(xiě)的過(guò)程中,通過(guò)人為的數(shù)據(jù)類(lèi)型變更的方法,確保程序計(jì)算中過(guò)程值和結(jié)果值的數(shù)據(jù)類(lèi)型的同質(zhì)性,從而達(dá)到保證計(jì)算精度準(zhǔn)確的目的。

        3 C語(yǔ)言中存儲(chǔ)位數(shù)溢出的控制

        同樣的例子,我們做一個(gè)簡(jiǎn)單的修改:

        Main()

        Float A;

        A=(float)4/5;

        Printf(“A=%10.8f\n”,A);

        Return 0;

        我們將輸出結(jié)果限定為10位有效數(shù)字,小數(shù)點(diǎn)后有效數(shù)字為8位。程序運(yùn)行后得到結(jié)果為:A=0.80000001。這顯然也不是我們想要的結(jié)果:A=0.80000000。為了知道這個(gè)原因,我們就必須了解C語(yǔ)言中浮點(diǎn)類(lèi)型數(shù)據(jù)的存儲(chǔ)格式要求。

        3.1 C語(yǔ)言中浮點(diǎn)類(lèi)型數(shù)據(jù)的存儲(chǔ)格式

        C語(yǔ)言中的浮點(diǎn)數(shù)是以IEEE 754標(biāo)準(zhǔn)的格式存儲(chǔ),與整型數(shù)據(jù)的存儲(chǔ)完全不一樣。

        3.1.1 單精度浮點(diǎn)型數(shù)據(jù)

        C語(yǔ)言中對(duì)float型數(shù)據(jù)(4個(gè)字節(jié))的表示分為三個(gè)部分:符號(hào)S,階碼E,尾數(shù)M。具體如下(見(jiàn)表1):

        表1 單精度浮點(diǎn)型數(shù)據(jù)存儲(chǔ)格式表

        1)最高位31位,保存符號(hào)位S,“0”表示正數(shù),“1”表示負(fù)數(shù)。[1]

        2)30位~23位,共8位,移碼方式(指數(shù)值加上偏移量127)保存指數(shù)部分,稱為階碼。

        3)22位~0位,共23位,保存系數(shù)部分,稱為尾數(shù),對(duì)于規(guī)范化二進(jìn)制數(shù),整數(shù)位的前導(dǎo)“1”不保存(隱含),直接保存小數(shù)部分b1b2…b23。

        實(shí)際上即是將十進(jìn)制數(shù)R在計(jì)算機(jī)中用二進(jìn)制數(shù)的科學(xué)計(jì)數(shù)法表示出來(lái):R=(-1)S×M×2E。

        而在float類(lèi)型的數(shù)據(jù)中,它的精度是由尾數(shù)的位數(shù)來(lái)決定的。浮點(diǎn)數(shù)在內(nèi)存中是按科學(xué)計(jì)數(shù)法來(lái)存儲(chǔ)的,其整數(shù)部分始終是一個(gè)隱含著的“1”,由于它是不變的,故不能對(duì)精度造成影響。

        float:2^23=8388608,一共七位,106>8388608>107這意味著最多能有7位有效數(shù)字,但絕對(duì)能保證的為6位,即float的精度為6~7位有效數(shù)字。因此,當(dāng)我們用“A=%10.8f\n”來(lái)控制輸出結(jié)果的小數(shù)位數(shù)為8位時(shí),就會(huì)出現(xiàn)精度丟失的問(wèn)題,即多出來(lái)了0.00000001。

        Float型的一些特殊約定:[2]

        2)當(dāng)E=0,M?。?時(shí),表示非規(guī)范化數(shù),即r=(-1)S×2-127×(0.M);

        3)當(dāng)E=255,M=0時(shí),表示無(wú)窮大,用符號(hào)位來(lái)確定是正無(wú)窮大還是負(fù)無(wú)窮大;

        4)當(dāng) E=255,M?。?時(shí),表示 NaN(Not a Number,不是一個(gè)數(shù));

        對(duì)于Double型,也有相似的約定。

        3.1.2 雙精度浮點(diǎn)型數(shù)據(jù)

        在控制輸出結(jié)果的實(shí)際位數(shù)的時(shí)候,我們必須考慮其存儲(chǔ)的精度值。因此可以通過(guò)提高變量的精度值定義的方式來(lái)盡量縮減這種誤差。例如,我們將上例改為:

        Main()

        通過(guò)查閱《中國(guó)煤炭工業(yè)年鑒2008》統(tǒng)計(jì)出1984年至2008年我國(guó)煤礦百萬(wàn)噸死亡率數(shù)據(jù)。根據(jù)對(duì)國(guó)家安全管理監(jiān)督總局(現(xiàn)改名為中華人民共和國(guó)應(yīng)急管理部)公報(bào)的搜集,整理出2009年至2017年我國(guó)煤礦百萬(wàn)噸死亡率數(shù)據(jù)[7,8]。得出我國(guó)近30年煤礦百萬(wàn)噸死亡率曲線走勢(shì)圖。如圖1所示。

        double A;

        A=(float)4/5;

        Printf(“A=%10.8f\n”,A);

        Return 0;

        結(jié)果:A=0.80000000

        分析:通過(guò)對(duì)于變量A的數(shù)據(jù)類(lèi)型精度的提高,將其由float變?yōu)閐ouble,而雙精度數(shù)據(jù)(double)其存儲(chǔ)范圍則擴(kuò)大了許多,從32位變?yōu)榱?4位(見(jiàn)表2)。

        表2 雙精度浮點(diǎn)型數(shù)據(jù)存儲(chǔ)格式表

        Double的精度:2^52=4503599627370496,一共16位,1015<4503599627370496<1016這意味著最多能有16位有效數(shù)字,但絕對(duì)能保證的為15位,即double的精度為15~16位有效數(shù)字。這樣就可以保證在指定8位有效數(shù)字時(shí)的數(shù)據(jù)的精度。

        同理,就算應(yīng)用雙精度,我們也需要注意指定的小數(shù)點(diǎn)后有效數(shù)位,不能夠超出其實(shí)際的有效位數(shù)。

        另外,long double型數(shù)能提供的十進(jìn)制數(shù)的有效數(shù)字不超過(guò)19位,即精度為18~19。但由于C語(yǔ)言沒(méi)有去充分實(shí)現(xiàn),其實(shí)際能提供的數(shù)據(jù)的精度與double型相當(dāng)。

        3.1.3 設(shè)定數(shù)據(jù)偏移量

        我們還可以使用在程序中加設(shè)數(shù)據(jù)偏移量的方法來(lái)盡量規(guī)避這種由于數(shù)據(jù)存儲(chǔ)類(lèi)型的限制而造成的誤差,假設(shè)我們?cè)O(shè)定數(shù)據(jù)偏移量為0.001,在printf程序語(yǔ)句前加上下面的控制程序:

        if(A-0.800<0.001?5)

        A=0.800;

        else

        A=0.800+0.001;}

        通過(guò)程序來(lái)控制數(shù)據(jù)的精度,可以得出最終的結(jié)果A=0.80000000。

        4 浮點(diǎn)數(shù)使用時(shí)的另外幾種易出現(xiàn)誤差的情況

        4.1 判斷兩個(gè)經(jīng)過(guò)運(yùn)算的浮點(diǎn)數(shù)相等

        由于浮點(diǎn)數(shù)是采用二進(jìn)制科學(xué)計(jì)數(shù)法來(lái)進(jìn)行存儲(chǔ)的,因此,絕大多數(shù)的小數(shù)在計(jì)算機(jī)內(nèi)存中是不能精確表示的。

        例如:如果兩個(gè)數(shù)x、y都是直接用常數(shù)賦值,這時(shí)我們判斷x,y是否相等。

        Main()

        float x=8.8,y=8.8;

        if(x==y(tǒng))

        printf("x=y(tǒng)\n");

        輸出:x=y(tǒng)

        如果我們將x或y改成經(jīng)過(guò)運(yùn)算后得到的值,這時(shí)我們?cè)賮?lái)判斷x,y是否相等:

        Main()

        float x=4.4+4.4,y=8.8;

        if(x==y(tǒng))

        printf("x=y(tǒng)\n");

        else

        printf("x! =y(tǒng)\n");

        輸出:x! =y(tǒng)從這個(gè)例子就可以發(fā)現(xiàn),C語(yǔ)言中浮點(diǎn)數(shù)的計(jì)算結(jié)果很多都是近似到浮點(diǎn)數(shù)的最大表示值來(lái)處理的,這樣一來(lái)就會(huì)造成誤差。因此,如果想判斷x是否等于y,應(yīng)該用兩數(shù)之差的絕對(duì)值和一個(gè)很小的數(shù)來(lái)比較,當(dāng)差值小于這個(gè)很小的數(shù)時(shí),我們就可以確定兩個(gè)數(shù)近似相等:fabs(x-y)<10-6。

        4.2 浮點(diǎn)數(shù)作為循環(huán)變量

        C語(yǔ)言中由于浮點(diǎn)數(shù)計(jì)算存在的誤差,可能會(huì)使循環(huán)次數(shù)達(dá)不到預(yù)定的次數(shù)而導(dǎo)致程序出現(xiàn)誤差,例如:

        main()

        float i j;

        for(i=1,j=0;i< =10;i+ =0.1)

        j+ =i;

        printf(“j=%f”,j);

        這個(gè)程序中,因?yàn)閕是浮點(diǎn)數(shù)計(jì)算取得值,會(huì)導(dǎo)致在循環(huán)到10的時(shí)候它的實(shí)際內(nèi)存存儲(chǔ)值變成10.000000001,這個(gè)值大于10,for語(yǔ)句會(huì)使程序循環(huán)終止,因此沒(méi)有達(dá)到預(yù)定的循環(huán)次數(shù),導(dǎo)致求和結(jié)果和我們本身想要的結(jié)果有誤差。

        4.3 一個(gè)很大的浮點(diǎn)數(shù)加上一個(gè)比較小的浮點(diǎn)數(shù)

        C語(yǔ)言中由于浮點(diǎn)數(shù)數(shù)據(jù)存儲(chǔ)有效位數(shù)的原因,可能會(huì)在計(jì)算一個(gè)很大數(shù)加上一個(gè)很小的數(shù)時(shí),小數(shù)計(jì)入大數(shù)累加時(shí)被溢出而造成誤差,例如:

        Main()

        float i,j,sum;

        i=1000000;j=0.1

        sum=i+j;

        printf(“sum=%f\n”,sum);

        return 0;

        因?yàn)閒loat一共只有6~7位有效數(shù)字(10進(jìn)制),如果整數(shù)部分的位數(shù)多了,相應(yīng)的小數(shù)部分的精確顯示位數(shù)就少了,因此當(dāng)一個(gè)很大的數(shù)(如100000)去加一個(gè)很小的數(shù)(如0.1),那么小數(shù)部分的數(shù)值就會(huì)因?yàn)榇鎯?chǔ)溢出而丟失,從而產(chǎn)生誤差,得不到我們想要的理論值1000000.1,而是1000000.0。

        5 結(jié)束語(yǔ)

        C語(yǔ)言程序編寫(xiě)時(shí),如果沒(méi)有很好地理解和掌握數(shù)據(jù)存儲(chǔ)和數(shù)據(jù)類(lèi)型轉(zhuǎn)換的問(wèn)題,那么在實(shí)際的編程中就會(huì)出現(xiàn)很多的誤差。特別是在做浮點(diǎn)型數(shù)據(jù)計(jì)算的過(guò)程中,由于內(nèi)存中存儲(chǔ)的方式多為乘2取整,所以計(jì)算機(jī)在精度范圍內(nèi)取舍時(shí)會(huì)導(dǎo)致數(shù)據(jù)出現(xiàn)誤差。在實(shí)際的編程中一定要注意C語(yǔ)言中浮點(diǎn)型數(shù)據(jù)的精度問(wèn)題。

        [1]張宗杰,張明亮.C語(yǔ)言中浮點(diǎn)數(shù)的存儲(chǔ)格式及其有效數(shù)字位數(shù)[J].計(jì)算機(jī)與數(shù)字工程,2006(1):84.

        [2]杜叔強(qiáng).淺析C語(yǔ)言中的浮點(diǎn)數(shù)[J].蘭州工業(yè)高等專(zhuān)科學(xué)校學(xué)報(bào),2010(5):26.

        Analysis on Precision of Floating-point Number for C Language

        ZHOU Guan?fang
        (Organizational and Personnel Department,Yunyang Teachers’College,Shiyan 420000,China)

        This article describes how data errors are caused in C language due to differentdata storagemethod with case study,an?alyses the reason for such errors and explains different storagemethods of floating point data in C language.Finally,some sugges?tions are proposed in this article.

        C Language;data precision;floating point data;relative error

        TP312

        A

        2095?8153(2015)03?0097?03

        2015?05?15

        周冠方(1984-),男,鄖陽(yáng)師范高等專(zhuān)科學(xué)校組織人事部助教。

        猜你喜歡
        程序
        給Windows添加程序快速切換欄
        試論我國(guó)未決羈押程序的立法完善
        失能的信仰——走向衰亡的民事訴訟程序
        “程序猿”的生活什么樣
        英國(guó)與歐盟正式啟動(dòng)“離婚”程序程序
        基于VMM的程序行為異常檢測(cè)
        偵查實(shí)驗(yàn)批準(zhǔn)程序初探
        我國(guó)刑事速裁程序的構(gòu)建
        創(chuàng)衛(wèi)暗訪程序有待改進(jìn)
        恐怖犯罪刑事訴訟程序的完善
        亚洲人成精品久久熟女| 三上悠亚免费一区二区在线| 亚洲免费视频网站在线| 亚洲天堂线上免费av| 久草青青91在线播放| 亚洲av无码专区在线播放中文| 久久这里只精品国产99热| 伊人久久无码中文字幕| 亚洲黄色性生活一级片| 色综合久久精品中文字幕| 全免费a级毛片免费看无码| 久久精品免视看国产成人| 亚洲AⅤ永久无码精品AA| av免费在线观看网站大全| 自拍视频在线观看国产| 欧洲女人与公拘交酡视频| 乱码精品一区二区三区| 国产成人久久综合热| 国产一区二区三区色区| 久久99天堂av亚洲av| 日本成本人片视频免费| 99精品国产兔费观看久久99| 亚洲综合一| 国产在线观看免费不卡视频| 精品人伦一区二区三区蜜桃91| 麻豆果冻传媒在线观看| 四虎影视久久久免费| 少妇久久一区二区三区| 国产成年人毛片在线99| 成人午夜福利视频镇东影视| 久久精品国产99久久丝袜| 国产精品亚洲精品专区| 风韵丰满熟妇啪啪区老熟熟女| 成人区人妻精品一区二区不卡网站| 国产福利姬喷水福利在线观看| 日本国产一区二区三区在线观看| 人妻经典中文字幕av| 免费无码中文字幕a级毛片| 日韩h网站| 国产成人美涵人妖视频在线观看| 欧洲成人一区二区三区|