5

The problem:

ceiling(31)
#31
ceiling(31/60*60)
#32

What is the correct way to fix this kind of errors?

Doing the multiplication before the division is not an option, my code looks something like this:

x <- 31/60
...
y <- ceiling(x*60)

I'm thinking of doing a new function:

ceil <- function(x) {
  ceiling(signif(x))
}

But I'm new to R, maybe there is a better way.

UPDATE
Sorry, I didn't give more details, I have the same problem in different parts of my code for different reasons, but always with ceiling.

I am aware of the rounding error in floating-point calculation. Maybe the title of the question could be improved, I don't want to fix an imprecision of the ceiling function, what I want to do is perhaps the opposite, make ceiling less exact. A way to tell R to ignore the digits that are clearly noise:

options(digits=17)
31/60*60
#31.000000000000004

But, apparently, the epsilon required to ignore the noise digits depends on the context of the problem.

pomber
  • 23,132
  • 10
  • 81
  • 94
  • 1
    possible duplicate of [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Pascal Cuoq Dec 24 '14 at 22:55
  • 6
    ceiling is exact, so there is no imprecision in it to fix. `/` and `*` on the other hand are not exact for all inputs, and since this is an intrinsic property of these floating-point operations, the fix is not to use them. – Pascal Cuoq Dec 24 '14 at 22:56
  • 3
    I don't see why this was downvoted. OP is not asking why this happens, but how to deal with it. A vvery reasonable question, well posed. – jlhoward Dec 24 '14 at 23:08
  • 4
    This seems to work (similar to your own solution): `ceiling(signif(31/60*60,-log10(.Machine$double.eps)))`. – jlhoward Dec 24 '14 at 23:09
  • Would either round() or ceiling(x-0.4) be beneficial? –  Dec 25 '14 at 02:24
  • @PascalCuoq I don't want to fix an imprecision of the ceiling function, see the update for more details. Feel free to change the title for a better one if that is what is giving the wrong idea. – pomber Dec 25 '14 at 17:23
  • @jlhoward that looks more robust than my solution, would you care to explain how it works in an answer? – pomber Dec 25 '14 at 17:26
  • 1
    note that `options(digits=...)` affects *output* precision, not floating-point imprecision in the calculations. – Ben Bolker Dec 25 '14 at 23:12
  • @BenBolker I know, I put it so I could be able to show the noise in the result – pomber Jan 08 '15 at 15:23

1 Answers1

1

The real problem here, I strongly believe, is found in my hero The Data Munger Guru's tagline, which is: "What is the problem that you are trying to solve? Tell me what you want to do, not how you want to do it. "

There are myriad cases where floating-point precision will cause apparent integers to turn into "integer +/- epsilon" , and so you need to figure out why you are going for "ceiling" , why you allow your values to not be integers, etc. <-- more or less what Pascal Cuoq wrote in his comment.

The solution to your concern thus depends on what's actually going on. Perhaps you want, say trunc(x/60)->y followed with trunc(y*60) , or maybe not :-) . Maybe you want y<-round(x/60*60) +1 , or jhoward's suggested approach. It depends, as I stress here, critically on what your goal is and how you want to deal with corner cases.

Carl Witthoft
  • 20,573
  • 9
  • 43
  • 73