10

I need a decimal variant of ceiling and floor functions. Something like signif with an option to choose in which direction to round.

For example, I need the number 2.63 to be transformed into 2.7, and not 3 (ceiling) or 2.6 (signif(2.63,2)).


The only solutions I can think of is to multiply by 10, then take ceiling and divide back by 10. ceiling(2.63*10)/10
I'm sure, there must be a more elegant solution.


My questions is quite similar to this one.

Community
  • 1
  • 1
ikashnitsky
  • 2,941
  • 1
  • 25
  • 43

3 Answers3

21

@42- answer in comment seems too useful to be just left in comment, hence this wiki-post.

You can create your own functions and adapt floor and ceiling fonctions, adding a level option to mimic the digits parameter of round function like this:

floor_dec <- function(x, level=1) round(x - 5*10^(-level-1), level)
ceiling_dec <- function(x, level=1) round(x + 5*10^(-level-1), level)

Examples:

# floor
floor_dec(1.259, 2)
[1] 1.25
floor_dec(1.9, 0)
[1] 1
floor_dec(29, -1)
[1] 20
floor_dec(1.251, 2)
[1] 1.25
floor_dec(1.2, 0)
[1] 1
floor_dec(23, -1)
[1] 20

# ceiling
ceiling_dec(1.259, 2)
[1] 1.26
ceiling_dec(1.9, 0)
[1] 2
ceiling_dec(29, -1)
[1] 30
ceiling_dec(1.251, 2)
[1] 1.26
ceiling_dec(1.2, 0)
[1] 2
ceiling_dec(23, -1)
[1] 30
Cath
  • 23,906
  • 5
  • 52
  • 86
  • 1
    @42- like I said, I found your custom function(s) deserved an answer because I think they can be useful to lots of people. I hope you don't mind, I won't mind deleting anyway, as long as the answer remain more visible than in comments ;-) – Cath Sep 21 '16 at 08:41
  • 1
    I agree with you. If such functions do not exist in `R` packages, I would suggest a pull request to a package like `useful` – ikashnitsky Sep 21 '16 at 11:57
  • For some reason ceiling_dec(1.35,2) = 1.36, but ceiling_dec(1.25,2) = 1.25. This doesn't seem like its doing what it's supposed to. – dule arnaux Oct 16 '17 at 18:55
  • @dulearnaux probably linked to https://stackoverflow.com/q/34845236/4137985 – Cath Oct 17 '17 at 07:00
  • I guess you cannot truly work around the round to even rule. But if you add `.Machine$double.eps` to `floor_dec` and subtract it from `ceiling_dec` you get pretty close. – jodis Apr 12 '18 at 03:56
1

This answer does not have the problem commented in previous answer, though sadly is based on the unwanted answer in the OP:

customCeiling <- function(x, Decimals=1) {
  x2<-x*10^Decimals
  ceiling(x2)/10^Decimals
}

customFloor <- function(x, Decimals=1) {
  x2<-x*10^Decimals
  floor(x2)/10^Decimals
}
Ferroao
  • 3,042
  • 28
  • 53
1

I want to define a very similar function to @42. Instead of having the floor function defined by how many decimal places you want, I want to define the number of sig figs:

floor_dec <- function(x, sigDig=1) {
  mostSig = ceiling(log10(abs(x)))
  floor(x*10^(sigDig-mostSig))*10^-(sigDig-mostSig)
}

> floor_dec(21.259, 4)
[1] 21.25
> floor_dec(21.259, 3)
[1] 21.2
> floor_dec(21.259, 2)
[1] 21
> floor_dec(21.259, 1)
[1] 20
> floor_dec(.259, 4)
[1] 0.259
> floor_dec(.259, 3)
[1] 0.259
> floor_dec(.259, 2)
[1] 0.25
> floor_dec(.259, 1)
[1] 0.2
> floor_dec(1.2, 0)
[1] 0
> floor_dec(23, -1)
[1] 0

Note that sigDif requires positive integers as input. Just like the prompter guesses, I find the position of the most significant digit, move the decimal place for the appropriate floor and then move the decimal place so that the input's most significant digit is the same as the output.

Jeff
  • 695
  • 1
  • 8
  • 19