Last active
October 8, 2024 18:58
-
-
Save mshafae/77d3cda92a90746210f3224c1cf83555 to your computer and use it in GitHub Desktop.
Demonstrating how doubles are approximating Real numbers and how direct comparison must be avoided.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Gist https://gist.github.com/mshafae/77d3cda92a90746210f3224c1cf83555 | |
// Filename cpsc120_double_comparison.cc | |
// CompileCommand clang++ -std=c++17 cpsc120_double_comparison.cc | |
// Demonstrating how doubles are approximating Real numbers and how direct | |
// comparison must be avoided. | |
#include <iomanip> | |
#include <iostream> | |
// lhs stands for "left hand side" | |
// rhs stands for "right hand side" | |
// For example: | |
// some_var == some_other_var | |
// some_var is lhs and some_other_var is rhs | |
bool DoubleSameAs(double lhs, double rhs, double epsilon) { | |
// If they're the same, we got lucky. | |
// Otherwise, check to see that lhs is + or - epsilon away from rhs. | |
return (lhs == rhs) || ((lhs - epsilon) < rhs && (lhs + epsilon) > rhs); | |
} | |
bool DoubleNotSameAs(double lhs, double rhs, double epsilon) { | |
return (lhs != rhs) && ((lhs - epsilon) > rhs || (lhs + epsilon) < rhs); | |
} | |
int main(int argc, char const *argv[]) { | |
std::cout << std::fixed; | |
std::cout << std::setprecision(20); | |
std::cout << "Floating point math works differently than what we expect.\n"; | |
if ((0.1 + 0.1 + 0.1) == 0.3) { | |
std::cout << "(0.1 + 0.1 + 0.1) is the same as 0.3\n"; | |
} else { | |
std::cout << "(0.1 + 0.1 + 0.1) is not the same as 0.3\n"; | |
} | |
// We want our doubles to be within 0.0000001 of each other to be considered | |
// the same. | |
double epsilon{1e-7}; | |
double a{123.456}; | |
double b{123.45600001}; | |
std::cout << "Safely comparing.\n"; | |
if (DoubleSameAs(a, b, epsilon)) { | |
std::cout << a << " is effectively the same as " << b << "\n"; | |
} else { | |
std::cout << a << " is not the same as " << b << "\n"; | |
} | |
std::cout << "Directly comparing.\n"; | |
if (a == b) { | |
std::cout << a << " is effectively the same as " << b << "\n"; | |
} else { | |
std::cout << a << " is not the same as " << b << "\n"; | |
} | |
a = 3.6; | |
b = (3.6 / 2.12) * 2.12; | |
std::cout << "Safely comparing.\n"; | |
if (DoubleSameAs(a, b, epsilon)) { | |
std::cout << a << " is effectively the same as " << b << "\n"; | |
} else { | |
std::cout << a << " is not the same as " << b << "\n"; | |
} | |
std::cout << "Directly comparing.\n"; | |
if (a == b) { | |
std::cout << a << " is effectively the same as " << b << "\n"; | |
} else { | |
std::cout << a << " is not the same as " << b << "\n"; | |
} | |
a = 1.01; | |
b = 0.99; | |
a = a - b; | |
b = 0.02; | |
std::cout << "Safely comparing."; | |
if (DoubleSameAs(a, b, epsilon)) { | |
std::cout << a << " is effectively the same as " << b << "\n"; | |
} else { | |
std::cout << a << " is not the same as " << b << "\n"; | |
} | |
std::cout << "Directly comparing.\n"; | |
if (a == b) { | |
std::cout << a << " is effectively the same as " << b << "\n"; | |
} else { | |
std::cout << a << " is not the same as " << b << "\n"; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment