0

In my program I put specific coordinates into a list. However, the algorithm sometimes puts the same coordinates into the list twice. In order to avoid that, I do the standard approach by comparing the EPSILON value to the absolute difference of both x and y values off all positions in the list:

bool doubleEqual(double x1, double y1, double x2, double y2){
    if( (fabs(x1-x2) < EPSILON) && (fabs(y1-y2) < EPSILON) ){
        return TRUE; // particle is already in list
    }
    return FALSE; // particle is not in the list
}

I have several questions:

1) Is this implementation to compare the position of two particles even correct?

2) How small can I choose EPSILON? (The particles can come really close to each other)

3) Is there any faster / or more robust implementation to compare the position of particles?

Gilfoyle
  • 3,282
  • 3
  • 47
  • 83
  • If you are placing something into a list based on exact position, you are using an integer concept. That's basically what you are doing with the epsilons - cutting away extra precision to turn the double compare into an integer compare. If you want to see overlap, I assume they have bounding geometry. Check that to see if there is a collision. – Michael Dorgan Aug 25 '17 at 18:21
  • `x1` and `x2` can be `1e+300` or `1e-300`. So what is their difference? – Bo Persson Aug 25 '17 at 18:24
  • 1
    `fabs(x1-x2) < EPSILON` is the wrong approach. It takes the "floating" out of "floating point" – chux - Reinstate Monica Aug 25 '17 at 18:25
  • 1
    If "the same coordinates into the list twice." is a problem, why not do `if( x1 == x2 && y1 == y2)`? Otherwise the issue is if the coordinates are _close_. A subtraction and compare to `EPSILON` fails to many cases. You have to present your definition of _close_ as there is not a universal one. – chux - Reinstate Monica Aug 25 '17 at 18:27
  • This QA is for C++ but it still could be something interesting for you. https://stackoverflow.com/questions/17333/what-is-the-most-effective-way-for-float-and-double-comparison – Support Ukraine Aug 25 '17 at 18:31
  • One _close_ definition converts the `double` into a `uint64_t` where the integer is the _canonical_ order of the `double` values. Then simply assess if the _canonical_ order is within 1,2 or what ever limit. – chux - Reinstate Monica Aug 25 '17 at 18:32
  • You probably want a relative diff: `static inline double reldiff(double x, double y) { double divisor = fmax(fabs(x), fabs(y)); /* If divisor is zero, both x and y are zero, so the difference between them is zero */ if (divisor == 0.0) return 0.0; return fabs(x - y) / divisor; }`. The test for zero is needed on a Mac; the result is `NaN` (or possibly `Inf` on other platforms) if the divisor is zero. Then you can look at `DBL_EPSILON` from `` and use that or a related value in the comparison. – Jonathan Leffler Aug 25 '17 at 18:32
  • @chux Does that really work? I thought I can not compare to double variables with `==` ? And yes, I mean the same coordinates (same particles = same position). Not just two double variables which are very close to each other. – Gilfoyle Aug 25 '17 at 18:41
  • https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ and the you can look for more deep numerical methods of comparing floats. – 0___________ Aug 25 '17 at 18:47
  • @JonathanLeffler Why divide the difference rather than multiply `DBL_EPSILON`? – EOF Aug 25 '17 at 18:55
  • @EOF: mainly because the function returns the value of the relative difference, rather than tying it to any particular threshold. Adding `DBL_EPSILON` to the function would decrease its generality. If that's what the OP wants, it is easy enough to modify the function to come up with a boolean answer (yes, within tolerance; no, not within tolerance). – Jonathan Leffler Aug 25 '17 at 19:15
  • @samuel you can compare with `==`, the problem is if they are close enough that both numbers have the same representation `==` will come out true, if that's not a problem for you then use `==`. If it is a problem, floats may be the wrong tool. the maion problem with == is that numbers can look the same but be different eg: `10*0.1` is often different from `1.0` – Jasen Aug 25 '17 at 22:14

1 Answers1

2

However, the algorithm sometimes puts the same coordinates into the list twice. In order to avoid that ...

yes, I mean the same coordinates (same particles = same position). Not just two double variables which are very close to each other.

To avoid to XY elements that are the same, a simple compare is sufficient

bool doubleEqual(double x1, double y1, double x2, double y2){
    return (x1 == x2) && (y1 == y2);
}

1) Is this implementation to compare the position of two particles even correct?

Using a fixed difference (epsilon) only makes sense over a narrow range of FP values. 1e100 and 2e100 as similarly different than 1e-100 and 2e-100 from a floating point point-of-view.

2) How small can I choose EPSILON? (The particles can come really close to each other)

To compare same-ness, use ==

3) Is there any faster / or more robust implementation to compare the position of particles?

Simply use ==


Code can compare doubles with ==, that is very useful for comparing equality, not closeness. If equality prevention is all that is needed, then if (x1 == x2 && y1 == y2) is sufficient.

The deeper issue is why "same coordinates into the list twice" a problem? IMO, that restriction is the problem. Use an algorithm that does not require that restriction.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256