how to return number of decimal places in R

Rollowing up on Roman's suggestion:

num.decimals <- function(x) {
    stopifnot(class(x)=="numeric")
    x <- sub("0+$","",x)
    x <- sub("^.+[.]","",x)
    nchar(x)
}
x <- "5.2300000"
num.decimals(x)

If your data isn't guaranteed to be of the proper form, you should do more checking to ensure other characters aren't sneaking in.


If someone here needs a vectorized version of the function provided by Gergely Daróczi above:

decimalplaces <- function(x) {
  ifelse(abs(x - round(x)) > .Machine$double.eps^0.5,
         nchar(sub('^\\d+\\.', '', sub('0+$', '', as.character(x)))),
         0)
}

decimalplaces(c(234.1, 3.7500, 1.345, 3e-15))
#> 1 2 3 0

Here is one way. It checks the first 20 places after the decimal point, but you can adjust the number 20 if you have something else in mind.

x <- pi
match(TRUE, round(x, 1:20) == x)

Here is another way.

nchar(strsplit(as.character(x), "\\.")[[1]][2])

You could write a small function for the task with ease, e.g.:

decimalplaces <- function(x) {
    if ((x %% 1) != 0) {
        nchar(strsplit(sub('0+$', '', as.character(x)), ".", fixed=TRUE)[[1]][[2]])
    } else {
        return(0)
    }
}

And run:

> decimalplaces(23.43234525)
[1] 8
> decimalplaces(334.3410000000000000)
[1] 3
> decimalplaces(2.000)
[1] 0

Update (Apr 3, 2018) to address @owen88's report on error due to rounding double precision floating point numbers -- replacing the x %% 1 check:

decimalplaces <- function(x) {
    if (abs(x - round(x)) > .Machine$double.eps^0.5) {
        nchar(strsplit(sub('0+$', '', as.character(x)), ".", fixed = TRUE)[[1]][[2]])
    } else {
        return(0)
    }
}

Tags:

R