C/C++浮點(diǎn)數(shù)使用的兩個(gè)注意事項(xiàng)詳解
一.回顧浮點(diǎn)數(shù)的存儲(chǔ)與讀取
浮點(diǎn)數(shù)的存入與讀取流程總覽:


二.浮點(diǎn)數(shù)使用的第一個(gè)注意事項(xiàng)
由于浮點(diǎn)數(shù)存入時(shí)很可能發(fā)生有效數(shù)值M二進(jìn)制序列的截?cái)嘁约氨唤厝サ男蛄械淖罡呶坏乃纳嵛迦攵斐删葥p失,所以?xún)蓚€(gè)浮點(diǎn)數(shù)直接用操作符進(jìn)行比較很可能會(huì)得到不符合預(yù)期的結(jié)果。
舉個(gè)例子:
int main()
{
float a = 3.12f;
a += 0.02f;
float b = 3.14f;
std::cout << (a == b) << std::endl;
std::cout << (a > b) << std::endl;
std::cout << (a < b) << std::endl;
return 0;
}簡(jiǎn)單調(diào)試一下代碼:


上述代碼中,a最終的值和b的值在數(shù)學(xué)上應(yīng)該是相同的,但是由于精度丟失而導(dǎo)致了最后a<b,如果這時(shí)a和b直接用運(yùn)算符進(jìn)行比較則無(wú)法得到預(yù)期的結(jié)果。

兩個(gè)浮點(diǎn)數(shù)的比較應(yīng)該使用如下方式:
對(duì)于浮點(diǎn)數(shù)而言比較合適的精度為:0.000001
對(duì)于雙進(jìn)度浮點(diǎn)數(shù)而言比較合適的精度為:0.0000000000000001
因此可以定義兩個(gè)宏:
#define epf 1e-6 #define epd 1e-16
f,f1,f2代表單精度浮點(diǎn)數(shù),d,d1,d2代表雙精度浮點(diǎn)數(shù)。
判斷浮點(diǎn)數(shù)是否等于0:
要判斷一個(gè)單精度浮點(diǎn)數(shù)是否等于0:if(fabs(f) <= eps );
要判斷一個(gè)雙精度浮點(diǎn)數(shù)是否等于0:if(fabs(d) <= epd);
判斷兩個(gè)浮點(diǎn)數(shù)是否相等:
要判斷兩個(gè)單精度浮點(diǎn)數(shù)是否相等:if(fabs(f1 - f2) <= eps);
要判斷兩個(gè)雙精度浮點(diǎn)數(shù)是否相等:if(fabs(d1 - d2) <= epd);
注:fabs是求浮點(diǎn)數(shù)絕對(duì)值的函數(shù)。聲明在<iostream>頭文件中。
#define eps 1e-6
int main()
{
float a = 3.12f;
a +=0.02f;
float b = 3.14f;
if (fabs(a - b) <= eps)
{
std::cout << "a==b" << std::endl;
}
else
{
std::cout << "a!=b" << std::endl;
}
return 0;
}
三.浮點(diǎn)數(shù)使用的第二個(gè)注意事項(xiàng)
由于浮點(diǎn)數(shù)存入時(shí)可能發(fā)生數(shù)據(jù)截?cái)?,因此兩個(gè)絕對(duì)值相差巨大的浮點(diǎn)數(shù)進(jìn)行加減運(yùn)算很多時(shí)候是沒(méi)有意義的。
以十進(jìn)制數(shù)為例來(lái)說(shuō)明這個(gè)問(wèn)題:

代碼驗(yàn)證:
int main()
{
float a = 1e38;
std::cout << a << std::endl;
float b = 1000;
a = a + b;
std::cout << a << std::endl;
a = a - b;
std::cout << a << std::endl;
return 0;
}
附: 觀察內(nèi)存中的FLT_MAX和FLT_MIN
C/C++中的FLT_MAX都被宏定義為浮點(diǎn)數(shù)絕對(duì)值最大的值
將FLT_MAX存入內(nèi)存中:


將a的二進(jìn)制序列分割為SEM的形式 :

其指數(shù)位不是全1
C/C++中的FLT_MIN被宏定義為絕對(duì)值最接近于0的浮點(diǎn)數(shù)
將FLT_MIN存入內(nèi)存中:


其指數(shù)位不是全0
補(bǔ)充:C 語(yǔ)言?xún)蓚€(gè)浮點(diǎn)數(shù)比較大小的辦法
浮點(diǎn)數(shù)并非真正意義上的實(shí)數(shù),只是其在某個(gè)范圍內(nèi)的近似。
因此兩個(gè)浮點(diǎn)數(shù)比較大小時(shí),不能簡(jiǎn)單地使用大于小于號(hào)進(jìn)行比較,應(yīng)該判斷連個(gè)浮點(diǎn)數(shù)差值的絕對(duì)值是否近似為0。
#include <stdio.h>
#include <math.h>
// 這里的 EPS 是自己定義的精度
#define EPS 1e-7 // 判斷浮點(diǎn)數(shù)是否位于0的一個(gè)很小的鄰域內(nèi)[-EPS,EPS]內(nèi)
int main(void)
{
/* 判斷一個(gè)浮點(diǎn)數(shù)是否等于 0*/
float a;
scanf("%f", &a);
if(fabs(a) <= EPS) // a=0
...
else if(a > EPS) // a>0
...
else // a<0
...
/* 比較兩個(gè)浮點(diǎn)數(shù)大小 */
float a,b;
scanf("%f%f",&a, &b);
if(fabs(a-b) <= EPS) // a=b
...
else if( (a-b) > EPS) // a>b
...
else // a<b
...
}
總結(jié)
到此這篇關(guān)于C/C++浮點(diǎn)數(shù)使用的兩個(gè)注意事項(xiàng)的文章就介紹到這了,更多相關(guān)C/C++浮點(diǎn)數(shù)注意事項(xiàng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言中棧的結(jié)構(gòu)和函數(shù)接口的使用示例
這篇文章主要介紹了C語(yǔ)言中棧的結(jié)構(gòu)和函數(shù)接口的使用,類(lèi)似很多軟件都有撤銷(xiāo)的操作,這其實(shí)就是用棧這種方法來(lái)實(shí)現(xiàn)的,當(dāng)然不同的軟件具體實(shí)現(xiàn)代碼會(huì)有差異,不過(guò)原理大多都是一樣的2023-02-02
C++開(kāi)發(fā)之PugiXML庫(kù)基礎(chǔ)用法示例詳解
PugiXML庫(kù)是一個(gè)功能強(qiáng)大、簡(jiǎn)單易用的C++ XML解析庫(kù),它提供了一組方便的函數(shù)來(lái)解析、創(chuàng)建和修改XML文檔,本文介紹了如何使用PugiXML庫(kù)來(lái)解析、創(chuàng)建和修改XML文檔,以及如何處理錯(cuò)誤和異常,感興趣的朋友跟隨小編一起看看吧2024-03-03
C++深入探究哈希表如何封裝出unordered_set和unordered_map
哈希表是一種根據(jù)關(guān)鍵碼去尋找值的數(shù)據(jù)映射結(jié)構(gòu),該結(jié)構(gòu)通過(guò)把關(guān)鍵碼映射的位置去尋找存放值的地方,說(shuō)起來(lái)可能感覺(jué)有點(diǎn)復(fù)雜,我想我舉個(gè)例子你就會(huì)明白了,最典型的的例子就是字典2022-06-06
C++實(shí)現(xiàn)班級(jí)成績(jī)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)班級(jí)成績(jī)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
淺談C++ 類(lèi)的實(shí)例中 內(nèi)存分配詳解
下面小編就為大家?guī)?lái)一篇淺談C++ 類(lèi)的實(shí)例中 內(nèi)存分配詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12
CMake 生成靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)的方法步驟
本文主要介紹了CMake 生成靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
C++開(kāi)發(fā)之CRC校驗(yàn)實(shí)例詳解
這篇文章主要介紹了C++開(kāi)發(fā)之CRC校驗(yàn)實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-07-07
采用C++實(shí)現(xiàn)區(qū)間圖著色問(wèn)題(貪心算法)實(shí)例詳解
這篇文章主要介紹了采用C++實(shí)現(xiàn)區(qū)間圖著色問(wèn)題(貪心算法),很經(jīng)典的算法問(wèn)題,需要的朋友可以參考下2014-07-07

