双可靠比较

Reliable comparison of double

我有一个公认的非常基本的问题:我需要比较 double>= 类型的两个数字。但是,出于某种原因,对于我知道小于阈值的值,我的代码计算结果为真。

编辑:我的代码(错误发生在 Antenna class 的 countTrig() 方法中):

#define k 0.0000000000000000000000138064852    // Boltzmann's constant

class Antenna{

    vector<vector<double> > output;

    int channels, smplrate, smpldur, samples, timethld;
    double resistance, temp, bandwidth, lnanoise, lnagain, RMS;

    public:
        Antenna(
            const int    _channels,   const int    _smplrate, const int    _smpldur,
            const double _resistance, const double _temp,     const double _bandwidth,
            const double _lnanoise,   const double _lnagain
        ){
            channels    = _channels;    smplrate    = _smplrate;    smpldur   = _smpldur;
            resistance  = _resistance;  temp        = _temp;        bandwidth = _bandwidth;
            lnanoise    = _lnanoise;    lnagain     = _lnagain;

            RMS     = 2 * sqrt(4 * k * resistance * temp * bandwidth);
            RMS    *= lnagain * pow(10,(lnanoise/10));
            samples = smplrate/smpldur;

            timethld = 508; //= (1/smplrate) * 0.127;

        }

        void genThrml(int units);
        void plotTrig(int timethld, double voltsthld);
        void plotThrml();
        int countTrig(double snrthld, int iter);

};

double fabs(double val){ if(val < 0){ val *= -1; } return val; }

void Antenna::genThrml(int units){

    output.resize(samples, vector<double>(channels));
    samples *= units;

    gRandom->SetSeed(time(NULL));
    for(int i = 0; i < samples; ++i){
        for(int j = 0; j < channels; ++j){
            output[i][j] = gRandom->Gaus(0,RMS);
        }
    }

}

void Antenna::plotThrml(){
    //Filler
}

int  Antenna::countTrig(double snrthld, int iter){

    int count = 0;

    int high = iter + timethld;
    int low  = iter - timethld;

    if(low < 0){ low = 0; }
    if(high > samples){ high = samples; }

    for(int i = low; i < high; ++i){

        for(int j = 0; j < channels; ++j){
           if(output[i][j] >= snrthld) count++; std::cout << output[i][j] << " " << snrthld << "\n";
        }
    }

    if(iter >= 3) return 1;
    else         return 0;

}

void Antenna::plotTrig(int timethld, double voltsthld){

    double snrthld = voltsthld / RMS;

    for(int i = 0; i < samples; ++i){
        for(int j = 0; j < channels; ++j){
            countTrig(snrthld, i);
        }
    }

}

int main(){

    Antenna test(20,4000,1,50,290,500000000,1.5,60);

    test.genThrml(1);
    test.plotTrig(400,0.0005);

    return 0;

}

阈值为 0.147417,我得到这样的输出:

 0.0014238 
-0.00187276

我相信我理解问题所在(除非我犯了一些明显的错误但没有发现),并且我理解浮点错误、精度等背后的原因。我,但是,知道这里的最佳实践是什么。什么是好的解决方案?我怎样才能可靠地比较 double 类型的值?这将用于对值的精确性和比较的可靠性非常重要的应用程序。

编辑:一个更小的例子:

int  countTrig(double snrthld, int iter, vector<vector<double> > output, int timethld){

    int count = 0;

    int high = iter + timethld;
    int low  = iter - timethld;

    if(low < 0){ low = 0; }
    if(high > 3){ high = 3; }

    for(int i = low; i < high; ++i){

        for(int j = 0; j < 3; ++j){
           if(fabs(output[i][j]) >= snrthld) count++; std::cout << output[i][j] << " " << snrthld << "\n";
        }
    }

    if(iter >= 3) return 1;
    else         return 0;

}

void plotTrig(int timethld, double snrthld){

vector<vector<double> > output = {{0.000028382, -0.0028348329, -0.00008573829},
                                  {0.183849939,  0.9283829020, -0.92838200021},
                                  {-0.00292889,  0.2399229929, -0.00081009189}};

    for(int i = 0; i < 3; ++i){
        for(int j = 0; j < 3; ++j){
            countTrig(snrthld, i, output, timethld);
        }
    }

}

int main(){

    plotTrig(1,0.1);
    return 0;

}

你打错了。

       if(output[i][j] >= snrthld) count++; std::cout << output[i][j] << " " << snrthld << "\n";

这一行的意思是

       if(output[i][j] >= snrthld)
         count++;
       std::cout << output[i][j] << " " << snrthld << "\n";

又名

       if(output[i][j] >= snrthld)
       {
         count++;
       }
       std::cout << output[i][j] << " " << snrthld << "\n";

你想要:

       if(output[i][j] >= snrthld)
       {
         count++;
         std::cout << output[i][j] << " " << snrthld << "\n";
       }