C中的Flout和0的比較

很清楚記得大學裏的某一天,老師讓我們寫出float x與“零值”比較的if語句,我興沖沖地2分鐘寫完上去演示,結果不知道這是個“套”~~~~~

當時只知道不能直接用float類型的值與0進行“= = ”或“! =”比較,但不知道該具體怎麼寫這個if語句。看過答案才知道,應該設法轉化成“> =”或“< =”,即:

const float EPSINON= 0.00001;

if ((x >= -EPSINON) && (x <= EPSINON))

看了答案後覺得很有道理,然後就記了答案,算是取得了“真經”了。

  但具體爲什麼大家來看看我們老師的答案 

例:

#include<stdio.h>

int main()

{

       float f = 1.0;

       float f1 = f/3;                                  // f1 = 1/3

       float f2 = f1*3;                          //f2 = 1;

       float f_result = f1 - f2/3;        //f_result = 0 ???

   

       if(0.0f == f_result)

       {

              printf("f_result ==0/n");

       }

       else

       {

              printf("f_result !=0/n");

       }

   

       return 0;

}

 

通過上述程序,可以明確得到答案,但具體爲什麼如此,還需要從C語言中float 類型變量的編碼格式說起。

 

浮點數表示形如V=x * 2^y 的有理數進行編碼,IEEE標準754仔細制定了浮點數及其運算的標準。

 

十進制的12.34可以這樣表示:1*10^1 + 2*10^0 + 3*10^-1 + 4*10^-2 。同樣地,二進制的101.11可以這樣表示:1*2^2 + 1*2^0 + 1*2^-1 +1*2^-2 。注意而今之中形如0.111…1 正好是小於1的數。假定只用有限長度的編碼,那麼十進制是不能準確表示想1/35/7這樣的數的,類似的,小數的二進制表示法只能表示那些能夠被寫成x * 2^y的數,其他的只能用近似數來表示。

 

IEEE 浮點標準用V=(-1)^s * M * 2^E的形式來表示一個數:

1)符號(sign s決定數是負數(s=1)還是正數(s=0 ),而對0的符號位作爲特殊情況處理。

2)有效數(significant M是一個二進制小數。

3)指數(exponent E是2 的冪(可能是負數),他的作用是對浮點數的加權。

一個浮點數的位表示按上述情形劃分爲3個域。

 

標準C語言中,單精度float浮點格式的符號位=1 ,有效位=23,指數未=8,產生一個32 位的表示。雙精度double浮點格式的符號位=1,有效位=52 ,指數位=11,產生一個64位的表示。

 

根據指數位的值,被編碼的值可以分爲三種不同的情況,即,規格化值、非規格化值、特殊數值。當指數的爲不全爲0且不全爲1 時,屬於規格化值;當指數位全爲0時,屬於非規格化值;當指數位全爲1時,屬於特殊數值。下面主要了解一下後兩者情況。

 

非規格化值有兩個目的。首先提供了一種表示數值0的方法當小數位也全爲0時,可以根據符號位的不同表示+0.0 -0.0。另外一個功能是用來表示那些非常接近0.0的數,使用逐漸下溢出(gradual underflow)的方法實現這個屬性。特殊數值當指數位全爲1,而小數位全爲0時,可以表示正無窮大和負無窮大。當小數位爲非零時,結果值被稱爲NaN

 

因爲表示方法限制了浮點數的範圍和精度,所以浮點運算只能近似地表示實數運算。系統需要使用“最接近”匹配值的值保存浮點值,這就是舍入(rounding)運算的任務。IEEE規定了四種舍入方式,默認的方式是向偶數舍入,也叫向最接近的值舍入。

 

 

浮點數的表示是不精確的,不能直接比較兩個數是否完全相等,一般都是在允許的某個範圍內認爲像個浮點數相等,如有兩個浮點數a,b,允許的誤差範圍爲1e-6,則abs(a-b)<=1e-6,即可認爲ab相等。還有一種方法就是擴大再取整,比如a=5.23,b=5.23,直接比較 a==b一般爲false,但是ab都擴大一百倍,然後強制轉換爲int類型,再用==比較就可以了

 

float型變量和零值比較的方法:

const float EPSINON = 0.000001;

if ((x >= - EPSINON) && (x <=EPSINON))

浮點型變量並不精確,其中EPSINON是允許的誤差(即精度),所以不可將float變量用“==”“!=”與數字比較,應該設法轉化成“>=”“<=”形式。如果寫成if x == 0.0),則是錯誤的。

因爲1.0在計算機中可能存爲0.9999991.00001等,很難恰好是1.0

 

哈哈終於寫完了 記住要小心老師的“圈套”。

發佈了33 篇原創文章 · 獲贊 10 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章