Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count the number of integer digits

Tags:

r

I want to count the number of digits before the decimal point for a numeric vector x with numbers greater or equal to 1. For example, if the vector is

x <- c(2.85, 356.01, 66.1, 210.0, 1445.11, 13.000)

my code should return a vector containing integers 1, 3, 2, 3, 4, 2

Does any know how to do this?

like image 867
Cindy Avatar asked Nov 08 '17 22:11

Cindy


People also ask

How do you count the number of digits in an integer?

The formula will be integer of (log10(number) + 1). For an example, if the number is 1245, then it is above 1000, and below 10000, so the log value will be in range 3 < log10(1245) < 4. Now taking the integer, it will be 3. Then add 1 with it to get number of digits.

How do you count the number of digits without a loop?

Now, we will see how to count the number of digits without using a loop. We can also count the number of digits with the help of the logarithmic function. The number of digits can be calculated by using log10(num)+1, where log10() is the predefined function in math. h header file.

How do you find the number of a digit?

So it can be concluded that to count number of digits, how many times a number is divided by 10 to reach 1 needs to be calculated. log base 10 of a number is the number of times a number needs to be divided by 10 to reach 1 but as 1 itself is not included in log base 10, 1 is added to get the number of digits.


2 Answers

This is probably the best way (for positive numbers):

floor(log10(x)) + 1

If you want an answer that works for negative numbers too, add in an abs():

floor(log10(abs(x))) + 1

The log10 method will not work if the input is exactly 0, so if you want a robust solution with that method, handle 0 as a special case:

n_int_digits = function(x) {
  result = floor(log10(abs(x)))
  result[!is.finite(result)] = 0
  result
}

You can also use nchar(trunc(x)), but this seems to behave poorly for large numbers. It will also count leading 0s, whereas the log method will not.

like image 70
Gregor Thomas Avatar answered Sep 28 '22 00:09

Gregor Thomas


Character Counting

For small problems, I like the nchar() solution the best, with one modification for negative values:

nDigits <- function(x) nchar( trunc( abs(x) ) )

# Test
nDigits(100)
nDigits(-100)
# both have 3 digits

nDigits(3)
nDigits(-3)
nDigits(0.1)
nDigits(-0.1)
# all have 1 digit

nDigits(1 / .Machine$double.eps)
nDigits(-1 / .Machine$double.eps)
# both have 16 digits

Base 10 Logarithm

If you want to make the logarithm solution work, then you need considerations for negative values and values between 0 and 1. To me, this solution is a tad more complicated:

nDigits2 <- function(x){

  truncX <- floor(abs(x))

  if(truncX != 0){
    floor(log10(truncX)) + 1
  } else {
    1
  }

}

Speed Performance

Here is the output from the microbenchmark comparison (100,000 reps). The code for the character-counting solution is simpler, but slower (by a factor of 3-4):

For integers > 1 (Unit: nanoseconds):

          expr  min   lq      mean median   uq     max neval
  nDigits(100) 1711 2139 2569.2819   2566 2994 2234046 1e+05
 nDigits2(100)    0  428  861.5435    856  856 5670216 1e+05

For really tiny decimals (Unit: nanoseconds):

                           expr  min   lq     mean median   uq     max neval
 nDigits(1/.Machine$double.eps) 2994 4277 5066.321   4705 4705 4477928 1e+05
nDigits2(1/.Machine$double.eps)  428 1283 1588.382   1284 1711 2042458 1e+05
like image 24
Gabriel J. Odom Avatar answered Sep 28 '22 00:09

Gabriel J. Odom