diff --git a/main.cpp b/main.cpp index 307289f..50fc2b7 100644 --- a/main.cpp +++ b/main.cpp @@ -1,30 +1,32 @@ +#include +#include #include -#include // for std::int64_t -#include // for assert -std::int64_t powint(std::int64_t base, int exp) +// 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) { - assert(exp >= 0 && "powint: exp parameter has negative value"); + return (std::abs(a - b) <= (std::max(std::abs(a), std::abs(b)) * relEpsilon)); +} - std::int64_t result{ 1 }; - while (exp) - { - if (exp & 1) { - std::cout << "a : " << result << "\n"; - result *= base; - } - std::cout << "b : " << exp << "\n"; - exp >>= 1; - std::cout << "c : " << base << "\n"; - base *= base; - } +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; - return result; + // Otherwise fall back to Knuth's algorithm + return (diff <= (std::max(std::abs(a), std::abs(b)) * relEpsilon)); } int main() { - std::cout << powint(7, 12); // 7 to the 12th power + // 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 }; - return 0; + 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 + + 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 }