Skip to content

Instantly share code, notes, and snippets.

@mshafae
Last active October 8, 2024 18:58
Show Gist options
  • Save mshafae/77d3cda92a90746210f3224c1cf83555 to your computer and use it in GitHub Desktop.
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.
// 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