Code:
//
// test program for the decibel function provided by someone else.
// main returns the number of errors discovered.
//
// exercise for reader: extend to include tests for special case values
// of V1 and V2. These depend on how you choose to handle them.
//
#include<iostream>
#define DIM(A) (sizeof(A)/sizeof(*(A)))
#define ABS(A) ((A) < 0 ? -(A) : (A))
#define MIN(A, B) ((A) < (B) ? (A) : (B))
struct {
double V2, V1, dB_expected;
} test[] = {
{0.100, 9.600, -39.6454246607913632},
{0.600, 9.100, -23.6178028387490002},
{1.100, 8.600, -17.8621153217068525},
{1.600, 8.100, -14.0873007244544990},
{2.100, 7.600, -11.1718859509374404},
{2.600, 7.100, -8.7257000149651454},
{3.100, 6.600, -6.5636448341519182},
{3.600, 6.100, -4.5805466848695939},
{4.100, 5.600, -2.7080834057292984},
{4.600, 5.100, -0.8962468883272455},
{5.100, 4.600, 0.8962468883272461},
{5.600, 4.100, 2.7080834057292993},
{6.100, 3.600, 4.5805466848695939},
{6.600, 3.100, 6.5636448341519182},
{7.100, 2.600, 8.7257000149651454},
{7.600, 2.100, 11.1718859509374404},
{8.100, 1.600, 14.0873007244544972},
{8.600, 1.100, 17.8621153217068525},
{9.100, 0.600, 23.6178028387489967},
{9.600, 0.100, 39.6454246607913632},
};
int tolerant_equal(double a, double b, double relerr, double abserr) {
double abserris = ABS(a - b);
return (abserris < MIN(ABS(a), ABS(b)) * relerr) || (abserris < abserr);
}
// supply the function decibel. It is passed the arguments V2 and V1 in that order.
double decibel(double, double);
int main() {
double V1, V2, expect, got;
unsigned i, errors = 0;
for (i = 0; i < DIM(test); ++i) {
V1 = test[i].V1;
V2 = test[i].V2;
expect = test[i].dB_expected;
got = decibel(V2, V1);
if (! tolerant_equal(got, expect, 1e-5, 1e-4)) {
++errors;
std::cout << "decibel(" << V2 << ", " << V1 << ") gave " << got << " expected " << expect << '\n';
}
}
return errors;
}