基于C++浮點(diǎn)數(shù)(float、double)類型數(shù)據(jù)比較與轉(zhuǎn)換的詳解
更新時(shí)間:2013年05月16日 17:00:47 作者:
本篇文章是對(duì)C++中浮點(diǎn)數(shù)(float、double)類型數(shù)據(jù)比較與轉(zhuǎn)換進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)機(jī)制和整型數(shù)不同,其有舍入誤差,在計(jì)算機(jī)中用近似表示任意某個(gè)實(shí)數(shù)。具體的說(shuō),這個(gè)實(shí)數(shù)由一個(gè)整數(shù)或定點(diǎn)數(shù)(即尾數(shù))乘以某個(gè)基數(shù)(計(jì)算機(jī)中通常是2)的整數(shù)次冪得到,這種表示方法類似于基數(shù)為10的科學(xué)記數(shù)法。
所以浮點(diǎn)數(shù)在運(yùn)算過(guò)程中通常伴隨著因?yàn)闊o(wú)法精確表示而進(jìn)行的近似或舍入。但是這種設(shè)計(jì)的好處是可以在固定的長(zhǎng)度上存儲(chǔ)更大范圍的數(shù)。
1、將字符串轉(zhuǎn)換為float、double過(guò)程存在精度損失,只是float、double各自損失的精度不相同而已
std::string str="8.2";
float cc=atof(str.c_str()); //cc的值為8.1999998
std::string str="8.2";
double cc=atof(str.c_str()); //cc的值為8.1999999999999993
2、將float、double轉(zhuǎn)換為字符過(guò)程中可能存在精度損失,但是通過(guò)%.8lf可以規(guī)避
(1)float小數(shù)點(diǎn)前后加起來(lái)有效數(shù)字只有6位。當(dāng)給定的float有效數(shù)在6位以內(nèi)轉(zhuǎn)換為字符不會(huì)丟失精度,當(dāng)有效位數(shù)大于6位就會(huì)存在精度丟失
//精度沒(méi)有丟失
char buf[100]={'\0'};
float aa=8000.25;
sprintf(buf,"%f",aa); //8000.250000
//精度沒(méi)有丟失
char buf[100]={'\0'};
float aa=8.00025;
sprintf(buf,"%f",aa); buf = 8.000250
//精度丟失,存在誤差
char buf[100]={'\0'};
float aa=8000.251;
sprintf(buf,"%f",aa); //8000.250977
//精度丟失,存在誤差此時(shí)使用.8lf也無(wú)效
char buf[100]={'\0'};
float aa=8000.251;
sprintf(buf,"%.8lf",aa); //8000.25097656
(2)double小數(shù)前后加起來(lái)的有效數(shù)字只有16位,當(dāng)給定的double有效數(shù)在16位以內(nèi)轉(zhuǎn)換為字符串不會(huì)丟失精度,當(dāng)有效位數(shù)大于16位湖影公寓存在精度丟失
存在誤差
char buf[100]={'\0'};
double aa=121.437565871234012;
sprintf(buf,"%.20lf",aa); //121.43756587123401000000
//沒(méi)有誤差
char buf[100]={'\0'};
double aa=8000.256165;
sprintf(buf,"%.8lf",aa);
std::cout <<buf<<std::endl; //8000.25616500
3、浮點(diǎn)數(shù)比較
用"=="來(lái)比較兩個(gè)double應(yīng)該相等的類型,返回真值完全是不確定的。計(jì)算機(jī)對(duì)浮點(diǎn)數(shù)的進(jìn)行計(jì)算的原理是只保證必要精度內(nèi)正確即可。
我們?cè)谂袛喔↑c(diǎn)數(shù)相等時(shí),推薦用范圍來(lái)確定,若x在某一范圍內(nèi),我們就認(rèn)為相等,至于范圍怎么定義,要看實(shí)際情況而已了,float,和double 各有不同
所以const float EPSINON = 0.00001;
if ((x >= - EPSINON) && (x <= EPSINON) 這樣判斷是可取的
至于為什么取0.00001,可以自己按實(shí)際情況定義
根據(jù)上面分析建議在系統(tǒng)開(kāi)發(fā)過(guò)程中設(shè)計(jì)到字符轉(zhuǎn)換建議采用double類型,精度設(shè)置為%.8lf即可,在比較浮點(diǎn)數(shù)十建議EPSINON = 0.00000001
所以浮點(diǎn)數(shù)在運(yùn)算過(guò)程中通常伴隨著因?yàn)闊o(wú)法精確表示而進(jìn)行的近似或舍入。但是這種設(shè)計(jì)的好處是可以在固定的長(zhǎng)度上存儲(chǔ)更大范圍的數(shù)。
1、將字符串轉(zhuǎn)換為float、double過(guò)程存在精度損失,只是float、double各自損失的精度不相同而已
std::string str="8.2";
float cc=atof(str.c_str()); //cc的值為8.1999998
std::string str="8.2";
double cc=atof(str.c_str()); //cc的值為8.1999999999999993
2、將float、double轉(zhuǎn)換為字符過(guò)程中可能存在精度損失,但是通過(guò)%.8lf可以規(guī)避
(1)float小數(shù)點(diǎn)前后加起來(lái)有效數(shù)字只有6位。當(dāng)給定的float有效數(shù)在6位以內(nèi)轉(zhuǎn)換為字符不會(huì)丟失精度,當(dāng)有效位數(shù)大于6位就會(huì)存在精度丟失
//精度沒(méi)有丟失
char buf[100]={'\0'};
float aa=8000.25;
sprintf(buf,"%f",aa); //8000.250000
//精度沒(méi)有丟失
char buf[100]={'\0'};
float aa=8.00025;
sprintf(buf,"%f",aa); buf = 8.000250
//精度丟失,存在誤差
char buf[100]={'\0'};
float aa=8000.251;
sprintf(buf,"%f",aa); //8000.250977
//精度丟失,存在誤差此時(shí)使用.8lf也無(wú)效
char buf[100]={'\0'};
float aa=8000.251;
sprintf(buf,"%.8lf",aa); //8000.25097656
(2)double小數(shù)前后加起來(lái)的有效數(shù)字只有16位,當(dāng)給定的double有效數(shù)在16位以內(nèi)轉(zhuǎn)換為字符串不會(huì)丟失精度,當(dāng)有效位數(shù)大于16位湖影公寓存在精度丟失
存在誤差
char buf[100]={'\0'};
double aa=121.437565871234012;
sprintf(buf,"%.20lf",aa); //121.43756587123401000000
//沒(méi)有誤差
char buf[100]={'\0'};
double aa=8000.256165;
sprintf(buf,"%.8lf",aa);
std::cout <<buf<<std::endl; //8000.25616500
3、浮點(diǎn)數(shù)比較
用"=="來(lái)比較兩個(gè)double應(yīng)該相等的類型,返回真值完全是不確定的。計(jì)算機(jī)對(duì)浮點(diǎn)數(shù)的進(jìn)行計(jì)算的原理是只保證必要精度內(nèi)正確即可。
我們?cè)谂袛喔↑c(diǎn)數(shù)相等時(shí),推薦用范圍來(lái)確定,若x在某一范圍內(nèi),我們就認(rèn)為相等,至于范圍怎么定義,要看實(shí)際情況而已了,float,和double 各有不同
所以const float EPSINON = 0.00001;
if ((x >= - EPSINON) && (x <= EPSINON) 這樣判斷是可取的
至于為什么取0.00001,可以自己按實(shí)際情況定義
根據(jù)上面分析建議在系統(tǒng)開(kāi)發(fā)過(guò)程中設(shè)計(jì)到字符轉(zhuǎn)換建議采用double類型,精度設(shè)置為%.8lf即可,在比較浮點(diǎn)數(shù)十建議EPSINON = 0.00000001
您可能感興趣的文章:
- C++數(shù)據(jù)精度問(wèn)題的解決方案(對(duì)浮點(diǎn)數(shù)保存指定位小數(shù))
- C++數(shù)據(jù)精度問(wèn)題(對(duì)浮點(diǎn)數(shù)保存指定位小數(shù))
- C++浮點(diǎn)數(shù)類型詳情
- C++實(shí)現(xiàn)浮點(diǎn)數(shù)精確加法
- 解析C++ 浮點(diǎn)數(shù)的格式化顯示
- 深入C/C++浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)方式詳解
- C++浮點(diǎn)型的存儲(chǔ)方式詳解
- C++浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)詳解
- C/C++浮點(diǎn)數(shù)使用的兩個(gè)注意事項(xiàng)詳解
- C++中浮點(diǎn)類型的具體使用
相關(guān)文章
如何使用VC庫(kù)函數(shù)中的快速排序函數(shù)
下面呢,小編就為大家介紹一下VC中庫(kù)函數(shù)qsort()的用法。需要的朋友可以過(guò)來(lái)參考下2013-09-09用C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器功能
這篇文章主要為大家詳細(xì)介紹了用C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01C++ 實(shí)現(xiàn)即時(shí)通信的示例代碼(直接運(yùn)行)
本文主要介紹了C++ 實(shí)現(xiàn)即時(shí)通信的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05C++ 遞歸遍歷文件并計(jì)算MD5的實(shí)例代碼
在本篇文章里小編給大家整理的是一篇關(guān)于C++ 遞歸遍歷文件并計(jì)算MD5的實(shí)例代碼,有興趣的朋友們可以學(xué)習(xí)參考下。2021-07-07基于C語(yǔ)言實(shí)現(xiàn)三子棋游戲的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用C語(yǔ)言數(shù)組實(shí)現(xiàn)簡(jiǎn)單的三子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07