Count number of digits in Kotlin
This task could be solved recursively as following:
- check it the number fits in the range
-9..9
. If that's true, the result is 1. - otherwise divide the number by 10, count digits in the result, and add 1 to that count.
fun numberOfDigits(n: Int): Int =
when (n) {
in -9..9 -> 1
else -> 1 + numberOfDigits(n / 10)
}
You can use the standard Java-math library in java.lang.Math
(edit: since Kotlin 1.2, use kotlin.math
). The log10
function will give you the length of the number minus 1 (with some exceptions). This function works with doubles though, so you have to convert back and forth.
A length
function could be written like this in Kotlin:
fun Int.length() = when(this) {
0 -> 1
else -> log10(abs(toDouble())).toInt() + 1
}
Then you can call it like this:
println(829.length()) // Prints 3
println((-1234).length()) // Prints 4 (it disregards the minus sign)
If for some reason you don't want to resort to strings or doubles, you can use binary search on an array of integers:
private val limits = arrayOf(-1, 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999)
fun countDigits(x: Int): Int {
assert(x >= 0)
val result = limits.binarySearch(x)
return result.xor(result.shr(31)) // one's complement absolute value
}
Of course, you could hard-code binary search for this specific use case if you wanted it to be really efficient, and/or you got paid by lines of code:
fun countDigits(x: Int): Int {
assert(x >= 0)
if (x <= 99999) {
if (x <= 99) {
if (x <= 9) {
return 1
} else {
return 2
}
} else {
if (x <= 999) {
return 3
} else {
if (x <= 9999) {
return 4
} else {
return 5
}
}
}
} else {
if (x <= 9999999) {
if (x <= 999999) {
return 6
} else {
return 7
}
} else {
if (x <= 99999999) {
return 8
} else {
if (x <= 999999999) {
return 9
} else {
return 10
}
}
}
}
}
Either way, make sure you got all those boundary cases right:
class CountDigitsTest {
@Test fun oneDigit() {
assertEquals(1, countDigits(0))
assertEquals(1, countDigits(9))
}
@Test fun twoDigits() {
assertEquals(2, countDigits(10))
assertEquals(2, countDigits(99))
}
@Test fun threeDigits() {
assertEquals(3, countDigits(100))
assertEquals(3, countDigits(999))
}
@Test fun fourDigits() {
assertEquals(4, countDigits(1000))
assertEquals(4, countDigits(9999))
}
@Test fun fiveDigits() {
assertEquals(5, countDigits(10000))
assertEquals(5, countDigits(99999))
}
@Test fun sixDigits() {
assertEquals(6, countDigits(100000))
assertEquals(6, countDigits(999999))
}
@Test fun sevenDigits() {
assertEquals(7, countDigits(1000000))
assertEquals(7, countDigits(9999999))
}
@Test fun eightDigits() {
assertEquals(8, countDigits(10000000))
assertEquals(8, countDigits(99999999))
}
@Test fun nineDigits() {
assertEquals(9, countDigits(100000000))
assertEquals(9, countDigits(999999999))
}
@Test fun tenDigits() {
assertEquals(10, countDigits(1000000000))
assertEquals(10, countDigits(Int.MAX_VALUE))
}
}
All of this assumes that you don't care about negative integers. If you do, and you have trouble adapting the code, feel free to ask for help.