What are the challenges in comparing floating point numbers?
Let’s run the following program first and observe the problem:
#include <iostream>using namespace std;int main(){double num1{ 100.0 - 99.99 }; // num1 should be equal to 0.01double num2{ 10.0 - 9.99 }; // num2 should be equal to 0.01cout<<"num1: "<<num1<<" num2: "<<num2<<endl;if (num1 == num2)cout << "Both numbers are equal." <<endl;else if (num1 > num2)cout << "First number is greater than the second." <<endl;else if (num1 < num2)cout << "First number is less than the second." <<endl;return 0;}
Have you observed the problem?
The program should display “Both numbers are equal.” however, it is displaying “First number is greater than the second.”.
Identify the problem
If we set the high precision value of these two numbers, we may notice that num1 will be equal to 0.0100000000000005116 and num2 will be equal to 0.0099999999999997868. Although both numbers are close to 0.01, but num1 is greater than num2.
Let’s execute the code below and notice the internal rounding error between these two numbers:
#include <iostream>#include <cmath>#include <iomanip>using namespace std;int main(){double num1{ 100.0 - 99.99 };double num2{ 10.0 - 9.99 };cout<<"num1: "<<setprecision(17)<<num1<<endl;cout<<"num2: "<<setprecision(17)<<num2<<endl;cout<<"Internal rounding error "<<setprecision(17)<<fixed<<num1-num2<<endl;}
Therefore, the issue is a result of an internal rounding error that appears when we use relational operators (==) to compare the equivalence of two numbers. This minor deviation is not merely an error but can cause substantial problems in real-time applications.
How to fix this issue
To fix this issue, we can find the absolute difference between these two numbers. This difference should compare with a small value, such as 10^-9, which is considered a negligible difference. If the absolute difference is less than this value, the two floating-point numbers can be considered equal.
#include <iostream>#include <cmath>using namespace std;int main(){double num1{ 100.0 - 99.99 }; // num1 should equal 0.01double num2{ 10.0 - 9.99 }; // num2 should equal 0.01if (abs(num1 - num2) < 1e-9)cout << "Both numbers are equal." <<endl;else if (abs(num1 - num2) > 1e-9)cout << "First number is greater than the second." <<endl;elsecout << "First number is less than the second." <<endl;return 0;}
Explanation
-
Line 7: The variable
num1is declared and initialized with the result of the expression100.0 - 99.99. The expected value ofnum1is0.01. -
Line 8: The variable
num2is declared and initialized with the result of the expression10.0 - 9.99. The expected value ofnum2is0.01. -
Line 10–15: The conditional statements are used to compare the absolute difference between
num1andnum2with a threshold value of1e-9(1multiplied by10to the power of-9). If the absolute difference is less than the threshold, it prints “Both numbers are equal.”. If the absolute difference is greater than the threshold, it prints “First number is greater than the second number.”. If neither of the above conditions is true, it prints “First number is less than the second number.”.
Free Resources