• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

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

      2015-02-13 01:28:39周冠方
      關(guān)鍵詞:浮點(diǎn)數(shù)浮點(diǎn)數(shù)據(jù)類型

      周冠方

      (鄖陽師范高等??茖W(xué)校組織人事部,湖北十堰420000)

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

      周冠方

      (鄖陽師范高等??茖W(xué)校組織人事部,湖北十堰420000)

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

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

      1 引言

      C語言程序設(shè)計(jì)的基本數(shù)據(jù)類型包含整型和浮點(diǎn)型兩類。在計(jì)算機(jī)中,實(shí)數(shù)特別是小數(shù)形式表示的數(shù)都是以浮點(diǎn)型數(shù)據(jù)來進(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語言中數(shù)據(jù)類型轉(zhuǎn)換帶來的影響

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

      Main()

      Float A;

      A=4/5;

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

      Return 0;

      結(jié)果:A=0.000000

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

      分析:在此程序中兩操作數(shù)4和5均為整型,運(yùn)算結(jié)果應(yīng)該為0.8,但是在C語言程序編寫中有這樣一個(gè)規(guī)則,C語言中計(jì)算的源數(shù)據(jù)為整形數(shù)據(jù),最終輸出結(jié)果也應(yīng)該為整形數(shù)據(jù)。“4/5”的結(jié)果0.8在C語言中會(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ì)算的過程中就將中間的操作數(shù)據(jù)更改為浮點(diǎn)型數(shù)據(jù),來確保最終結(jié)果數(shù)據(jù)和中間操作數(shù)據(jù)的數(shù)據(jù)類型的同質(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)镃語言程序設(shè)計(jì)中,不同數(shù)據(jù)類型之間的計(jì)算問題時(shí),我們必須規(guī)定明確的數(shù)據(jù)類型,并且在算法編寫的過程中,通過人為的數(shù)據(jù)類型變更的方法,確保程序計(jì)算中過程值和結(jié)果值的數(shù)據(jù)類型的同質(zhì)性,從而達(dá)到保證計(jì)算精度準(zhǔn)確的目的。

      3 C語言中存儲(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語言中浮點(diǎn)類型數(shù)據(jù)的存儲(chǔ)格式要求。

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

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

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

      C語言中對(duì)float型數(shù)據(jù)(4個(gè)字節(jié))的表示分為三個(gè)部分:符號(hào)S,階碼E,尾數(shù)M。具體如下(見表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ù)法表示出來:R=(-1)S×M×2E。

      而在float類型的數(shù)據(jù)中,它的精度是由尾數(shù)的位數(shù)來決定的。浮點(diǎn)數(shù)在內(nèi)存中是按科學(xué)計(jì)數(shù)法來存儲(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”來控制輸出結(jié)果的小數(shù)位數(shù)為8位時(shí),就會(huì)出現(xiàn)精度丟失的問題,即多出來了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í),表示無窮大,用符號(hào)位來確定是正無窮大還是負(fù)無窮大;

      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ǔ)的精度值。因此可以通過提高變量的精度值定義的方式來盡量縮減這種誤差。例如,我們將上例改為:

      Main()

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

      double A;

      A=(float)4/5;

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

      Return 0;

      結(jié)果:A=0.80000000

      分析:通過對(duì)于變量A的數(shù)據(jù)類型精度的提高,將其由float變?yōu)閐ouble,而雙精度數(shù)據(jù)(double)其存儲(chǔ)范圍則擴(kuò)大了許多,從32位變?yōu)榱?4位(見表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ù)字不超過19位,即精度為18~19。但由于C語言沒有去充分實(shí)現(xiàn),其實(shí)際能提供的數(shù)據(jù)的精度與double型相當(dāng)。

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

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

      if(A-0.800<0.001?5)

      A=0.800;

      else

      A=0.800+0.001;}

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

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

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

      由于浮點(diǎn)數(shù)是采用二進(jìn)制科學(xué)計(jì)數(shù)法來進(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)過運(yùn)算后得到的值,這時(shí)我們?cè)賮砼袛鄕,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語言中浮點(diǎn)數(shù)的計(jì)算結(jié)果很多都是近似到浮點(diǎn)數(shù)的最大表示值來處理的,這樣一來就會(huì)造成誤差。因此,如果想判斷x是否等于y,應(yīng)該用兩數(shù)之差的絕對(duì)值和一個(gè)很小的數(shù)來比較,當(dāng)差值小于這個(gè)很小的數(shù)時(shí),我們就可以確定兩個(gè)數(shù)近似相等:fabs(x-y)<10-6。

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

      C語言中由于浮點(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語句會(huì)使程序循環(huán)終止,因此沒有達(dá)到預(yù)定的循環(huán)次數(shù),導(dǎo)致求和結(jié)果和我們本身想要的結(jié)果有誤差。

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

      C語言中由于浮點(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é)束語

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

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

      [2]杜叔強(qiáng).淺析C語言中的浮點(diǎn)數(shù)[J].蘭州工業(yè)高等??茖W(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-),男,鄖陽師范高等專科學(xué)校組織人事部助教。

      猜你喜歡
      浮點(diǎn)數(shù)浮點(diǎn)數(shù)據(jù)類型
      LEO星座增強(qiáng)GNSS PPP模糊度浮點(diǎn)解與固定解性能評(píng)估
      詳談Java中的基本數(shù)據(jù)類型與引用數(shù)據(jù)類型
      四種Python均勻浮點(diǎn)數(shù)生成方法
      如何理解數(shù)據(jù)結(jié)構(gòu)中的抽象數(shù)據(jù)類型
      基于浮點(diǎn)DSP的鐵路FSK信號(hào)檢測(cè)
      在C語言中雙精度浮點(diǎn)數(shù)線性化相等比較的研究
      非精確浮點(diǎn)數(shù)乘法器設(shè)計(jì)
      基于FPGA的浮點(diǎn)FIR濾波器設(shè)計(jì)
      改進(jìn)的Goldschmidt雙精度浮點(diǎn)除法器
      Visual Basic處理浮點(diǎn)DSP芯片數(shù)據(jù)的方法
      准格尔旗| 尚志市| 盐津县| 屏南县| 庄浪县| 平原县| 永康市| 绥中县| 息烽县| 咸宁市| 鸡东县| 象州县| 东至县| 萨迦县| 中江县| 新河县| 宜良县| 洪雅县| 深泽县| 天全县| 寿宁县| 化州市| 宁城县| 朝阳市| 抚顺市| 汤原县| 海宁市| 灵丘县| 三门县| 清涧县| 上杭县| 鄂伦春自治旗| 谷城县| 湄潭县| 靖江市| 沅陵县| 黎平县| 郑州市| 堆龙德庆县| 蒲城县| 新宾|