一篇文章帶你了解C語言浮點(diǎn)數(shù)之間的比較規(guī)則
你認(rèn)為這段代碼輸出什么?
int main() { float f1 = 1.1; float f2 = 2.2; if (f2 - 1.1 == f1) printf("等于"); else printf("不等于"); return 0; }
答案是不等于。
為什么不等于呢?
因?yàn)樵贑語言中浮點(diǎn)數(shù)是存在精度損失的,有可能比原來的數(shù)大,也有可能小。 在下圖所示,f1在打印小數(shù)點(diǎn)后30位時(shí)就能很明顯的看出存在精度損失。
應(yīng)該怎么解決?
浮點(diǎn)數(shù)不能直接用 == 號(hào)比較。那么應(yīng)該怎么比較呢。
這里要引出精度這個(gè)概念,精度可以理解為引發(fā)一個(gè)浮點(diǎn)數(shù)發(fā)生改變的最小值。
當(dāng)一個(gè)浮點(diǎn)數(shù)加上精度或者減去精度,都不等于該數(shù)本身。
精度可以是自己定義的,也可以用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類型的默認(rèn)精度,DBL_EPSILON 為double類型的精度。
那么怎么判斷兩個(gè)浮點(diǎn)數(shù) f1 和 f2 相等呢。
雖然兩個(gè)浮點(diǎn)數(shù)存在精度上的誤差,但這個(gè)誤差非常小,只要(f2 - f1)這個(gè)差值在負(fù)精度到正精度的區(qū)間內(nèi),就可以認(rèn)為它們相等。
如圖,它們的差值必須在 (-XXX_EPSILON,XXX_EPSILON) 這個(gè)區(qū)間內(nèi),才能說明它們相等。
偽代碼
if(f2 - f1) > -XXX_EPSILON && (f2 - f1)< XXX_EPSION){相等;}
可以簡化為 >>
if (fabs(f2 - f1) < XXX_EPSILON) //fabs函數(shù)求絕對值,在math.h頭文件中{相等;}
怎么判斷浮點(diǎn)數(shù)等于0?
這個(gè)浮點(diǎn)數(shù)的絕對值小于精度,可以認(rèn)為這個(gè)數(shù)為0。
if (fabs(f1) < XXX_EPSILON) { //f1為0 }
還有一個(gè)問題
// 判斷f1為0的條件 < 能換成 <= 嗎
if (fabs(f1) < XXX_EPSILON) ->> if (fabs(f1) <= XXX_EPSILON)
0的性質(zhì):任何數(shù)加上0,都等于它本身。
而上述也講了精度的定義為浮點(diǎn)數(shù)加上XXX_ESILON 都會(huì)發(fā)生改變,如果 f1 可以等于 XXX_ESILON ,不是說一個(gè)浮點(diǎn)數(shù)加上0會(huì)發(fā)生改變嗎,這明顯不符合0的性質(zhì)。所以是開區(qū)間,只能是 < 。
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
- C語言深入探索浮點(diǎn)數(shù)的使用秘密
- C語言中浮點(diǎn)數(shù)的精度丟失問題解決
- C語言入門之浮點(diǎn)數(shù)
- C語言如何把浮點(diǎn)數(shù)轉(zhuǎn)換為字符串
- C語言中的浮點(diǎn)數(shù)據(jù)類型
- C語言數(shù)據(jù)(整數(shù)、浮點(diǎn)數(shù))在內(nèi)存中的存儲(chǔ)
- C語言中魔性的float浮點(diǎn)數(shù)精度問題
- C語言菜鳥基礎(chǔ)教程之單精度浮點(diǎn)數(shù)與雙精度浮點(diǎn)數(shù)
- C語言詳細(xì)分析浮點(diǎn)數(shù)在內(nèi)存中的儲(chǔ)存
相關(guān)文章
C++中線性代數(shù)計(jì)算Eigen庫的使用教程詳解
Eigen是一個(gè)基于線性代數(shù)的C++模板庫,主要用于矩陣、向量、數(shù)值求解和相關(guān)算法,本文主要為大家簡單聊聊Eigen庫的使用,希望對大家有所幫助2023-12-12基于C++實(shí)現(xiàn)去除字符串頭尾指定字符功能
編程時(shí)我們經(jīng)常需要對字符串進(jìn)行操作,其中有一項(xiàng)操作就是去除字符串的頭(尾)指定的字符,比如空格。本文為大家詳細(xì)介紹了如何利用C++實(shí)現(xiàn)這一效果,需要的可以參考一下2022-04-04C++超詳細(xì)講解隱藏私有屬性和方法的兩種實(shí)現(xiàn)方式
為了避免因?yàn)閷㈩悗熘械乃接谐蓡T開放給類的使用方而導(dǎo)致的軟件邏輯外泄,因此需要將對外代碼中的私有成員隱藏起來,下面我們來了解一下隱藏私有屬性和方法的兩種實(shí)現(xiàn)方式2022-05-05VS2022創(chuàng)建Windows服務(wù)程序的方法步驟
本文主要介紹了VS2022創(chuàng)建Windows服務(wù)程序的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05詳解C++編程中的重載流插入運(yùn)算符和流提取運(yùn)算符
這篇文章主要介紹了詳解C++編程中的重載流插入運(yùn)算符和流提取運(yùn)算符,是C語言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09如何利用C++實(shí)現(xiàn)mysql數(shù)據(jù)庫的連接池詳解
為了提高M(jìn)ySQL數(shù)據(jù)庫的訪問的瓶頸,除了在服務(wù)器端增設(shè)緩存服務(wù)器緩存常用的數(shù)據(jù)之外(如redis),還可以增加數(shù)據(jù)庫連接池,來提高M(jìn)ySQL Server的訪問效率,這篇文章主要給大家介紹了關(guān)于如何利用C++實(shí)現(xiàn)mysql數(shù)據(jù)庫的連接池的相關(guān)資料,需要的朋友可以參考下2021-07-07

C語言深入探究水仙花數(shù)與變種水仙花數(shù)代碼