2022-08-15 16:13:57 +01:00
|
|
|
#include <algorithm>
|
|
|
|
#include <cmath>
|
2022-08-12 14:59:08 +01:00
|
|
|
#include <iostream>
|
2022-08-13 00:34:25 +01:00
|
|
|
|
2022-08-15 16:13:57 +01:00
|
|
|
// return true if the difference between a and b is within epsilon percent of the larger of a and b
|
|
|
|
bool approximatelyEqualRel(double a, double b, double relEpsilon)
|
2022-08-15 12:48:53 +01:00
|
|
|
{
|
2022-08-15 16:13:57 +01:00
|
|
|
return (std::abs(a - b) <= (std::max(std::abs(a), std::abs(b)) * relEpsilon));
|
|
|
|
}
|
2022-08-15 12:48:53 +01:00
|
|
|
|
2022-08-15 16:13:57 +01:00
|
|
|
bool approximatelyEqualAbsRel(double a, double b, double absEpsilon, double relEpsilon)
|
|
|
|
{
|
|
|
|
// Check if the numbers are really close -- needed when comparing numbers near zero.
|
|
|
|
double diff{ std::abs(a - b) };
|
|
|
|
if (diff <= absEpsilon)
|
|
|
|
return true;
|
2022-08-15 15:08:54 +01:00
|
|
|
|
2022-08-15 16:13:57 +01:00
|
|
|
// Otherwise fall back to Knuth's algorithm
|
|
|
|
return (diff <= (std::max(std::abs(a), std::abs(b)) * relEpsilon));
|
2022-08-15 12:48:53 +01:00
|
|
|
}
|
|
|
|
|
2022-08-12 14:59:08 +01:00
|
|
|
int main()
|
|
|
|
{
|
2022-08-15 16:13:57 +01:00
|
|
|
// a is really close to 1.0, but has rounding errors
|
|
|
|
double a{ 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 };
|
|
|
|
|
|
|
|
std::cout << approximatelyEqualRel(a, 1.0, 1e-8) << '\n'; // compare "almost 1.0" to 1.0
|
|
|
|
std::cout << approximatelyEqualRel(a-1.0, 0.0, 1e-8) << '\n'; // compare "almost 0.0" to 0.0
|
2022-08-15 12:49:34 +01:00
|
|
|
|
2022-08-15 16:13:57 +01:00
|
|
|
std::cout << approximatelyEqualAbsRel(a, 1.0, 1e-12, 1e-8) << '\n'; // compare "almost 1.0" to 1.0
|
|
|
|
std::cout << approximatelyEqualAbsRel(a-1.0, 0.0, 1e-12, 1e-8) << '\n'; // compare "almost 0.0" to 0.0
|
2022-08-12 14:59:08 +01:00
|
|
|
}
|