I have an admittedly very basic problem: I need to compare two numbers of type double
for >=
. For some reason, however, my code evaluates to true for values I know to be less than the threshold.
EDIT: My code (the error occurs in the countTrig()
method of the Antenna
class):
#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;
}
With a threshold of 0.147417, I get output like this:
0.0014238
-0.00187276
I believe I understand the problem (unless there's some obvious mistake I've made and not caught), and I understand the reasoning behind floating point errors, precision, etc. I don't, however, know, what the best practice is here. What is a good solution? How can I reliably compare values of type double
? This will be used in an application where it is very important that values be precise and comparisons be reliable.
EDIT: A smaller example:
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;
}