1. 程式人生 > >C++ float資料精度丟失問題

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有效數在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

比如要判斷點數

floatA和B是否相等,我們先令float  x = A –B ;

並設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;
    }