John Threepwood
John Threepwood

Reputation: 16143

Is there a Scala-way to get the length of a number?

I would like to know, if there is a Scala built-in method to get the length of the decimal representation of an integer ?

Example: 45 has length 2; 10321 has length 5.

One could get the length with 10321.toString.length, but this smells a bit because of the overhead when creating a String object. Is there a nicer way or a built-in method ?

UPDATE:

Upvotes: 3

Views: 5307

Answers (9)

Vled
Vled

Reputation: 95

Most people gave the most efficient answer of (int) log(number)+1 But I want to get a bit deeper into understanding why this works.

Let N be a 3 digit number. This means N can be any number between 100 and 1000, or :

100 < N < 1000 => 10^2 < N < 10^3

The Logarithmic function is continuous , therefore :

log(10^2) < log(N) < log(10^3) => 2 < log(N) < 3

We can conclude that N's logarithm is a number between 2 and 3 , or in other words , any 3 digit numbers' logarithm is between 2 and 3.

So if we take only the integer part of a numbers logarithm(eg. the integer part of 2.567 is 2) and add 1 we get the digit length of the number.

Upvotes: 0

Rajasekhar
Rajasekhar

Reputation: 2345

Here is the solution:

number.toString.toCharArray.size     

input - output

45   -   2
100  -   3

Upvotes: -1

Maxence Cramet
Maxence Cramet

Reputation: 594

Another possibility can be:

private lazy val lengthList = (1 until 19).map(i => i -> math.pow(10, i).toLong)

def numberSize(x: Long): Int =
  if (x >= 0) positiveNumberSize(x)
  else positiveNumberSize(-x) + 1

private def positiveNumberSize(x: Long): Int =
  lengthList
    .collectFirst {
      case (l, p) if x < p => l
    }
    .getOrElse(19)

Upvotes: 0

Vlad Vlaskin
Vlad Vlaskin

Reputation: 110

Something like this should do the job:

def numericLength(n: Int): Int = BigDecimal(n).precision

Upvotes: 3

Luigi Plinge
Luigi Plinge

Reputation: 51109

If you want speed then something like the following is pretty good, assuming random distribution:

def lengthBase10(x: Int) =
  if      (x >= 1000000000) 10
  else if (x >= 100000000)   9
  else if (x >= 10000000)    8
  else if (x >= 1000000)     7
  else if (x >= 100000)      6
  else if (x >= 10000)       5
  else if (x >= 1000)        4
  else if (x >= 100)         3
  else if (x >= 10)          2
  else                       1

Calculating logarithms to double precision isn't efficient if all you want is the floor.

The conventional recursive way would be:

def len(x: Int, i: Int = 1): Int = 
  if (x < 10) i 
  else len(x / 10, i + 1)

which is faster than taking logs for integers in the range 0 to 10e8.

lengthBase10 above is about 4x faster than everything else though.

Upvotes: 4

tgr
tgr

Reputation: 3608

The easiest way is:

def numberLength(i : Int): Int = i.toString.length

You might add a guarding-condition because negative Int will have the length of their abs + 1.

Upvotes: 1

bseibold
bseibold

Reputation: 529

This is definitely personal preference, but I think the logarithm method looks nicer without a branch. For positive values only, the abs can be omitted of course.

def digits(x: Int) = {
    import math._
    ceil(log(abs(x)+1)/log(10)).toInt
}

Upvotes: 6

ntalbs
ntalbs

Reputation: 29458

toString then get length of int will not work for negative integers. This code will work not only for positive numbers but also negatives.

def digits(n:Int) = if (n==0) 1 else math.log10(math.abs(n)).toInt + 1;

Upvotes: 4

Dale Myers
Dale Myers

Reputation: 2821

Take log to the base 10, take the floor and add 1.

Upvotes: 2

Related Questions