浮點數在內存中的存儲機制喝整形數據不同,有舍入誤差,在計算機中用近似表示任意某個實數。具體來說,這個數由一個整數或定點數(即尾數)乘以某個基數(計算機中通常是2)的整數次冪得到。這種表示方法類似於基數為10的科學計數法。所以浮點數在運算過程中隨着因為無法精確表示而進行的近似或舍入。但是這種設計的好處是可以在固定的長度上存儲更大范圍的數。
1、將字符串轉化為float、double過程存在精度損失,只是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轉換為字符串的過程中可能存在精度損失,但是通過%.8lf可以規避
2.1 float小數點前后加起來有效數字只有6位,當給定的float有效數在6位以內轉換為字符串時不會丟失精度,當有效位數大於6位就會存在精度丟失。
//精度沒有丟失 char buf[100]={'\0'}; float aa=8000.25; sprintf(buf,"%f",aa); //8000.250000 //精度沒有丟失 char buf[100]={'\0'}; floataa=8.00025; sprintf(buf,"%f",aa); buf = 8.000250 //精度丟失,存在誤差 charbuf[100]={'\0'}; float aa=8000.251; sprintf(buf,"%f",aa); //8000.250977 //精度丟失,存在誤差此時使用.8lf也無效 char buf[100]={'\0'}; float aa=8000.251; sprintf(buf,"%.8lf",aa);//8000.25097656
2.2 double小數前后加起來的有效數字只有16位,當給定的double有效數在16位數以內轉換為字符串時不會丟失精度,當有效位數大於16位就會出現精度丟失。出現誤差。
char buf[100]={'\0'}; double aa=121.437565871234012; sprintf(buf,"%.20lf",aa);//121.43756587123401000000 //沒有誤差 char buf[100]={'\0'}; double aa=8000.256165; sprintf(buf,"%.8lf",aa); std::cout<<buf<<std::endl; //8000.25616500
3、浮點數的比較
使用==來比較兩個double應該相等的類型,返回真值完全是不確定的。計算機對浮點數的進行計算原理是只保障必要精度內正確即可。
我們在判斷兩個浮點數是否相等時,推薦用范圍來確定,若x在一定范圍內,我們就認為相等,至於范圍定義視情況而定,float喝double各有所不同。
所以:
const float EPSINON = 0.00001; if((x >= - EPSINON) && (x <= EPSINON) // 這樣判斷是可取的,至於為什么取0.00001可按實際情況定義 也可以 abs(x) <= EPSINON 比如要判斷浮點數float A和B是否相等,我們先令: float x = A - B ; 並設 constfloat EPSINON = 0.00001; 則 if ((x >= - EPSINON)&& (x <= EPSINON);//或者if(abs(x) <= EPSINON) cout<<”A 與B相等<<endl; else cout<<”不相等”<<endl;
根據上面分析建議在系統開發過程中涉及到字符轉換建議采用double類型,精度設置為%.8lf即可。在比較浮點數時建議EPSINON=0.00000001。