Reputation: 16143
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
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
Reputation: 2345
Here is the solution:
number.toString.toCharArray.size
input - output
45 - 2
100 - 3
Upvotes: -1
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
Reputation: 110
Something like this should do the job:
def numericLength(n: Int): Int = BigDecimal(n).precision
Upvotes: 3
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
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
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
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