一篇文章帶你瞭解C語言浮點數之間的比較規則

你認為這段代碼輸出什麼?

int main()
{
	float f1 = 1.1;
	float f2 = 2.2;
	if (f2 - 1.1 == f1)
		printf("等於");
	else
		printf("不等於");
	return 0;
}

答案是不等於。

在這裡插入圖片描述

為什麼不等於呢?

因為在C語言中浮點數是存在精度損失的,有可能比原來的數大,也有可能小。 在下圖所示,f1在打印小數點後30位時就能很明顯的看出存在精度損失。

在這裡插入圖片描述

應該怎麼解決?

浮點數不能直接用 == 號比較。那麼應該怎麼比較呢。

這裡要引出精度這個概念,精度可以理解為引發一個浮點數發生改變的最小值。

當一個浮點數加上精度或者減去精度,都不等於該數本身。

精度可以是自己定義的,也可以用C語言自帶的,它定義在 float.h 頭文件中。

#define FLT_EPSILON      1.192092896e-07F        // smallest such that 1.0+FLT_EPSILON != 1.0
#define DBL_EPSILON      2.2204460492503131e-016 // smallest such that 1.0+DBL_EPSILON != 1.0

FLT_EPSILON 為float類型的默認精度,DBL_EPSILON 為double類型的精度。

那麼怎麼判斷兩個浮點數 f1 和 f2 相等呢。

雖然兩個浮點數存在精度上的誤差,但這個誤差非常小,隻要(f2 – f1)這個差值在負精度到正精度的區間內,就可以認為它們相等。

如圖,它們的差值必須在 (-XXX_EPSILON,XXX_EPSILON) 這個區間內,才能說明它們相等。

在這裡插入圖片描述

偽代碼

if(f2 - f1) > -XXX_EPSILON  && (f2 - f1)< XXX_EPSION){相等;}

可以簡化為 >>

if (fabs(f2 - f1) < XXX_EPSILON) //fabs函數求絕對值,在math.h頭文件中{相等;}

怎麼判斷浮點數等於0?

這個浮點數的絕對值小於精度,可以認為這個數為0。

if (fabs(f1) < XXX_EPSILON)
{
	//f1為0
}

還有一個問題

// 判斷f1為0的條件 < 能換成 <= 嗎

if (fabs(f1) < XXX_EPSILON) ->>  if (fabs(f1) <= XXX_EPSILON) 

0的性質:任何數加上0,都等於它本身。
而上述也講瞭精度的定義為浮點數加上XXX_ESILON 都會發生改變,如果 f1 可以等於 XXX_ESILON ,不是說一個浮點數加上0會發生改變嗎,這明顯不符合0的性質。所以是開區間,隻能是 < 。

總結

本篇文章就到這裡瞭,希望能給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!

推薦閱讀: