C++ float資料精度丟失問題
將float、double轉換為字元過程中可能存在精度損失,但是通過%.8lf可以規避
(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)double小數前後加起來的有效數字只有16位
用"=="來比較兩個double應該相等的型別,返回真值完全是不確定的。計算機對浮點數的進行計算的原理是隻保證必要精度內正確即可。
我們在判斷浮點數相等時,推薦用範圍來確定,若x在某一範圍內,我們就認為相等,至於範圍怎麼定義,要看實際情況而已了,float,和double 各有不同 所以const float EPSINON = 0.00001; if((x >= - EPSINON) && (x <= EPSINON) 這樣判斷是可取的至於為什麼取0.00001,可以自己按實際情況定義。
也可以 abs(x) <= EPSINON
比如要判斷浮點數
並設const float EPSINON = 0.00001; 則
if ((x >= - EPSINON)&& (x <= EPSINON);//或者if(abs(x) <= EPSINON)
cout<<”A 與B相等<<endl; else cout<<”不相等”<<endl;
根據上面分析建議在系統開發過程中設計到字元轉換建議採用double型別,精度設定為%.8lf即可,在比較浮點數十建議EPSINON= 0.00000001
誤差累計的解決辦法:
如下所示:
輸出為382525,顯然誤差非常大。
float f = 0.1;
float sum = 0;
for( int i=0; i<4000000; i++)
{
sum += f;
}
改進後輸出為400001,將40W拆分成2K和2K,避免了大數與小數相加後產生的階段誤差,控制資料的有效數字在6位以內。
float f = 0.1;
float sum = 0;
for( int i=0; i<2000; i++)
{
float tmp_sum =0;
for (int j = 0;j<2000;j++){
tmp_sum+=f;
}
sum += tmp_sum;
}