1

This is a common problem discussed before and very well explained HERE

However, all the answers I've found all explain different ways to handle equality, but I don't think any of them are particularly good or readable in code and most importantly cannot be used for other operators such as <, >, <=, >= or ! (not).

My preferred method is using rounding, but only for comparisons as below:

> options(digits = 20)
> x <- cbind(c(1:10)/100*9,c(1:10)/10,c(1:10)/100)
> x
                      [,1]                [,2]                 [,3]
 [1,] 0.089999999999999997 0.10000000000000001 0.010000000000000000
 [2,] 0.179999999999999993 0.20000000000000001 0.020000000000000000
 [3,] 0.270000000000000018 0.29999999999999999 0.029999999999999999
 [4,] 0.359999999999999987 0.40000000000000002 0.040000000000000001
 [5,] 0.450000000000000011 0.50000000000000000 0.050000000000000003
 [6,] 0.540000000000000036 0.59999999999999998 0.059999999999999998
 [7,] 0.630000000000000115 0.69999999999999996 0.070000000000000007
 [8,] 0.719999999999999973 0.80000000000000004 0.080000000000000002
 [9,] 0.809999999999999942 0.90000000000000002 0.089999999999999997
[10,] 0.900000000000000022 1.00000000000000000 0.100000000000000006

> x[,1]==x[,2]-x[,3]
 [1] FALSE FALSE  TRUE FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE
> round(x[,1],15)==round(x[,2]-x[,3],15)
 [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
> round(x[,1],15)<=round(x[,2]-x[,3],15)
 [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

Rounding close the precision limit gives good results and will work with other operators and to me seems easier to read than other functions but I figure will still cause it's own error at times.

Is there a best practice method to deal with this error that is compact and easily readable, and can be used with multiple operators?

Or even better, is it possible to have a set of alternate operators such as ~== or ~<= that will automatically round to precision limits such that I don't need to constantly think about them?

Edit To better explain why I asked this question is that this is more than just handling equality. Which has already been answered.

However from my example in row 3 0.270000000000000018 > .27 and 0.29999999999999999 > .3 and 0.029999999999999999 < .03. but the sum is 0.30000000000000004 not 0.29999999999999999 so These are the cases where < and > will break as well, as values can arbitrarily become < or >.

In this case I would add or subtract a small value .27 + .02 < .3 +.000001 but that always changes on a case by case or even a use by use basis.

I am working with data where I am doing comparisons and I am constantly seeing errors specifically with < and > and I have to constantly make code adjustments to deal with it. I want something so that I don't need to add so much extra code to deal with this.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
MichaelE
  • 763
  • 8
  • 22
  • 3
    Any reason you tagged c++? – UKMonkey Dec 01 '17 at 15:13
  • you dont need to take any extra precautions for operators `<`,`>`,etc. they will just work as expected (within the accuracy of floating points). If you wanted to take care of accuracy you would need a third possible result for eg `<`, something like "cannot decide because they are too close", but even that you dont need because you can first do a `==` comparison (with some delta) and only then do the `<`. .....or I completely misunderstand the question ;) – 463035818_is_not_an_ai Dec 01 '17 at 15:16
  • 3
    While this is a well-written question, I think that the overlap with the linked-to question is large enough for this to be a duplicate. As @tobi303 points out, inequalities are not really the issue, so I don't think that the fact that the other question doesn't discuss them is enough to justify a new question. – John Coleman Dec 01 '17 at 15:46
  • I edited the question to hopefully better explain why < and > comparisons are bigger problems that equality. As far as the c++ tag, SO recommended the c++ tag so I added it. C++ obviously has similar rounding issues, but it seems better behaved with comparisons. – MichaelE Dec 01 '17 at 16:36
  • still not completely clear. what exactly do you mean with "These are the cases where < and > will break as well". What values become arbitrary < or > than what ? – 463035818_is_not_an_ai Dec 01 '17 at 17:36
  • It is of course true that if two numbers are approximately equal to each other and the distance between them is so small that it is swamped by floating point round-off error, then you can't reliably tell which of them is larger than another. That problem is intrinsic to such calculations. No trick with rounding will be able to eliminate it. You either need to use a library for higher precision calculations, or use a different algorithm (e.g. one that involves rescaling data or maybe using log probabilities rather than probabilities). – John Coleman Dec 01 '17 at 19:26

0 Answers0