This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Most effective way for float and double comparison
How dangerous is it to compare floating point values?
I have const float M = 0.000001; and float input;. I want to not equality check on them. But I know direct check has side effect M != input. So, my question how I can compare two float value without side effect ?
const double epsilon = 1e-12;
if(fabs(input - M) < epsilon) //input == M
{
//...
}
if(fabs(input - M) >= epsilon) // input != M
{
//...
}
The smaller the value of epsilon the more accurate the comparison is, therefore the more the probablity that it will tell you that two values are not equal whereas you wanted them to be considered equal. The larger the value of epsilon, the more the probability that it will tell you the results are equal when in fact you wanted them to be not equal. The value of epsilon should be chosen in accordance with the specifics of the task at hand.
When comparing floats, you have to compare them for being "close" instead of "equal." There are multiple ways to define "close" based on what you need. However, a typical approach could be something like:
namespace FloatCmp {
const float Eps = 1e-6f;
bool eq(float a, float b, float eps = Eps) {
return fabs(a - b) < eps;
}
//etc. for neq, lt, gt, ...
}
Then, use FloatCmp::eq() instead of == to compare floats.
Related
This question already has an answer here:
Floating-point arithmetic: why would order of addition matter?
(1 answer)
Closed last year.
I have two vectors of double. The value of the double is between -1000 and 1000.
Both vectors contain the same numbers, but the order is different.
For example
Vector1 = {0.1, 0.2, 0.3, 0.4};
Vector2 = {0.4, 0.2, 0.1, 0.3};
Is there a guarantee that the sum of Vector1 will be exactly equal to the sum of Vector2, assuming the sum is done via:
double Sum = 0;
for (double Val : Vector) Sum += Val;
I am worried about double imprecisions.
Is there a guarantee that the sum of Vector1 will be exactly equal to the sum of Vector2, assuming the sum is done via:
No, there is no such guarantee in the C++ language.
In fact, there is an indirect practical guarantee - assuming typical floating point implementation - that the results would be unequal. (But compilers have ways of disabling such guarantees, and of enabling unsafe floating point optimisations that may cause the sum to be equal).
The difference is likely to be very small with the given input, but it can be very large with other inputs.
No, they are not guaranteed to be the same. Here's a simple concrete example:
#include <stdio.h>
int main(void) {
double x = 504.4883585687764;
double y = 29.585946026264367;
double z = 2.91427392498775;
double lhs = x + (y + z);
double rhs = z + (y + x);
printf("LHS : %5.30g\n", lhs);
printf("RHS : %5.30g\n", rhs);
printf("Equal: %s\n", lhs == rhs ? "yes" : "no");
return 0;
};
When run, this produces:
LHS : 536.988578520028568163979798555
RHS : 536.988578520028454477142076939
Equal: no
Read this and in general something about floating points.
Note that if you adding value of different magnitude they will be rounded in different way if order is changed giving a bit different result.
I'm doing Gram-Schmidt Orthogonalization process. At some point I'm getting output 3D vectors with values extremely small. Basically the values are zeros. How to deal with values such as -3.5527136788005009 * 10^-15?
How to convert them to zero or compare if it is almost zero?
You asked "How to convert them to zero?" If you want to convert extremely small values to zero you can use a simple if statement:
const double delta = 0.000000001;
if (x < delta && x > -delta) { x = 0; }
I did research on my old code and I've found this little func:
static const double eps = 1e-10;
bool isZero(double value) const
{
return std::abs(value) <= eps;
}
I want to compare floats. I had a problem when comparing equality so I used epsilon and it was solved
inline bool isEqual(float x, float y)
{
const float epsilon = 1e-5;
return abs(x - y) <= epsilon * abs(x);
}
but I also want to compare other comparisons such as '>' and '<='
I have two floats = 49 but when executing f1 > f2 it returns true.
I have tried this function:
inline bool isSmallerOrEqual(float x, float y)
{
const float epsilon = 0.01;
return epsilon * abs(x) <= epsilon * abs(y);
}
It worked but not for all values.
Any ideas ?
First, your isEquals function may be wrong, you're using the relative epsilon version. This version is works better with extremely large numbers, but breaks down when using extremely small numbers. The other version would be to use absolute epsilon. This version works well with small numbers (including extremely small numbers), but breaks down with extremely large numbers.
inline bool epsilonEquals(const float x, const float y, const float epsilon = 1E-5f)
{
return abs(x - y) <= epsilon;
}
Second, calling it isEquals is inaccurate, the function is generally known as Epsilon Equals because it doesn't validate that 2 numbers are equal, it validates that they are reasonably close to each other within a small margin of error (epsilon).
Third, if you want to check that 2 numbers are less than or equal to each other then you generally don't need or even want an epsilon equals function involved, doing so only increases the likelihood of false positive. If you do want to use epsilon comparison you can take advantage of paulmckenzie's method:
inline bool epsilonLessThanOrEqualTo(const float x, const float y, const float epsilon = 1E-5f)
{
return x <= y || epsilonEquals(x, y, epsilon);
}
If you want to have an epsilon not-equals method you can simply check that the absolute difference between the 2 numbers is larger than epsilon.
I was trying to add float values (all have one precision) through for loop, and then compare the result value with a normal declared float. But I was not getting the answers right.
I solved it by converting the floats to int by multiplying each with 10, then compare it with value*10
I try to write a std::map< Vector3D, double > where colinear (parallel or anti-parallel) vectors should share the same key.
As a compare function I use the following function (with a 1e-9 tolerance in isEqualEnough()) that I created with the help of Using a (mathematical) vector in a std::map
struct Vector3DComparator
{
bool operator() (const Vector3D& lhsIn, const Vector3D& rhsIn) const
{
Vector3D lhs = lhsIn.absolute(); // make all members positive
Vector3D rhs = rhsIn.absolute();
if ((lhs.z < rhs.z))
return true;
if ((isEqualEnough(lhs.z, rhs.z))
&& (lhs.y < rhs.y))
return true;
if ((isEqualEnough(lhs.z, rhs.z))
&& (isEqualEnough(lhs.y, rhs.y))
&& (lhs.x < rhs.x))
return true;
return false;
}
};
When I insert the normals of a cube into my map I should get 3 different values (because I don't care about the direction) but I get 4:
x=1 y=0 z=0
x=0 y=1 z=0
x=0 y=0 z=1
x=0 y=2.2e-16 z=1
The compare function is somehow wrong but whenever I try to fix it I get an assert telling me "Expression: invalid comparator".
Anyone spots the mistake?
It is mathematically impossible to use a tolerance with relational operators and yield a strict weak ordering. Any kind of convergence criterion will fail to satisfy ordering algorithms and data structures requirements. The reason is very simple: the incompatibility of two values, using a tolerance, doesn't yield an equivalence relation since it is not transitive. You may have almostEqual(a, b) and almostEqual(b, c) and yet ~almostEqual(a, c). Try this using a=1.0; b=2.0; c=3.0; tolerance=1.5;. You may look at this answer: Is floating-point == ever OK?.
You may still define an equivalence relation on floats using truncation, floor, roof, or round kind of functions. Let's define for example less3(a, b) if and only if floor(a * 8) < floor(b * 8) assuming a and b are binary floats and are not NAN and multiplications doesn't yield both the same signed infinite; this compares a and b using 3 bits of precision (0.125 in decimal). Now define equiv3(a, b) if and only if !less3(a, b) && ~less3(b, a). It can be shown that eqiv3(a, b) yields an appropriate equivalence relation. Since less3 is an order relation and equiv3 is an equivalence relation, then less3 is a strict weak order on floats (excluding NANs). Furthermore, in the case a * 8 == +INF && b * 8 == +INF || a * 8 == -INF && b * 8 == -INF you may fallback with ordinary < operator on floats.
Combining the answer from Julien Villemure-Fréchette with the link posted by #alterigel I made my comparison function work:
struct Vector3DComparator
{
bool operator() (const Vector3D& lhsIn, const Vector3D& rhsIn) const
{
int p = 100000; // precision factor
Vector3D lhs = lhsIn.absolute(); // make all members positive
Vector3D rhs = rhsIn.absolute();
auto lhsTied = std::tie((int)(lhs.x * p), (int)(lhs.y * p), (int)(lhs.z * p));
auto rhsTied = std::tie((int)(rhs.x * p), (int)(rhs.y * p), (int)(rhs.z * p));
return lhsTied < rhsTied;
}
};
Please note: This code contains bad style like c-style casts, bad naming and more. My functions and classes are different to the ones posted here. I just stripped everything away to make it easy to understand.
EDIT:
I noticed two more mistakes:
First: It didn't always work for nearly identical vectors.
Based on #tetorea last comment on my question I changed the function to always get very similar values compared. I use the dot product for that as it is ±1 (or at least close to) for parallel vectors.
Second: .absolute() was not working because with this function two vectors (-1,1,0) and (1,1,0) were considered parallel which they are clearly not.
In the code below you can find the corrected version:
struct Vector3DComparator
{
bool operator() (const Vector3D& lhs, const Vector3D& rhs) const
{
if (isEqualEnough(fabs(lhs * rhs), 1.0)) // dot product
return false;
int p = 100000; // precision factor
auto lhsTied = std::tie((int)(lhs.x * p), (int)(lhs.y * p), (int)(lhs.z * p));
auto rhsTied = std::tie((int)(rhs.x * p), (int)(rhs.y * p), (int)(rhs.z * p));
return lhsTied < rhsTied;
}
};
I have two double variable. double a = 0.10000, double b = 0.1. How can I make sure the comparison (a == b) is always true ?
If you are being paranoid about using == on doubles or floats (which you should be) you can always check that they are close within a small tolerance.
bool same = fabs(a-b) < 0.000001;
The other answers here require you to scale the tolerance factor manually, which I wouldn't advise. For instance if you are comparing two numbers less than one millionth, one answer will always say the two numbers are "close enough." The other answer instead leaves it to the caller to specify which is equally error-prone.
I would instead suggest something like the following function. It will return 0 if the two doubles are within the stated range of each other, otherwise -1 (if d1 is smaller), or +1. Using fabs() may require you to link with the math library, such as with -lm.
#include <algorithm> // for max()
#include <cmath> // for fabs()
int double_compare( double d1, double d2 ) {
double dEpsilon = .00000001;
double dLarger = std::max( std::fabs(d1), std::fabs(d2) );
double dRange = dLarger * dEpsilon;
if ( std::fabs( d1 - d2 ) < dRange )
return 0;
return d1 < d2 ? -1: 1;
}
New answer to old question, but using epsilons is the way to go, check this example:
bool equals(const double a, const double b, const double maxRelativDiff = numeric_limits<double>::epsilon()) {
double difference = fabs(a - b);
const auto absoluteA = fabs(a);
const auto absoluteB = fabs(b);
double biggerBoi = (absoluteB > absoluteA) ? absoluteB : absoluteA; // Get the bigger number
return difference <= (biggerBoi * maxRelativDiff);
}
In this case you're checking if they are equal up to maxRelativDiff, so 0.0001 == 0.0001.
Check: https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon