计算Kotlin

时间:2017-03-22 11:50:10

标签: kotlin

我正在使用简单的string.length方法计算位数:

val number = 829
val length = number.toString().length

我想知道这是否是一种好方法,或者在Kotlin中有更合适的方法。

5 个答案:

答案 0 :(得分:15)

您可以在java.lang.Math中使用标准的Java数学库。 log10函数将为您提供数字长度减1(有一些例外)。此功能适用于双打,因此您必须来回转换。

在Kotlin中可以这样写出length函数:

fun Int.length() = when(this) {
    0 -> 1
    else -> Math.log10(Math.abs(toDouble())).toInt() + 1
}

然后你可以这样称呼它:

println(829.length()) // Prints 3
println(-1234.length()) // Prints 4 (it disregards the minus sign)

答案 1 :(得分:1)

如果由于某种原因你不想求助于字符串或双精度,你可以对整数数组使用二进制搜索:

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
}

当然,如果您希望它真正有效,并且/或者您通过代码行获得报酬,那么您可以对这个特定用例进行硬编码二进制搜索:

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
                }
            }
        }
    }
}

无论哪种方式,请确保所有这些边界情况都正确:

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))
    }
}

所有这些都假定您不关心负整数。如果您这样做,并且您在调整代码时遇到困难,请随时寻求帮助。

答案 2 :(得分:0)

可以按以下方式递归解决此任务:

  • 检查该数字是否在-9..9范围内。如果是这样,则结果为1。
  • 否则,将数字除以10,对结果中的数字进行计数,然后将该数字加1。
fun numberOfDigits(n: Int): Int = 
    when (n) {
        in -9..9 -> 1
        else -> 1 + numberOfDigits(n / 10)
    } 

答案 3 :(得分:0)

如果不仅只有数字。 例如:“ -11.345F”

y = (1212, 900, 730, 714, 650, 591, 565, 500, 450, 440, 430, 420, 407, 381, 324, 315, 283)
x = []
for i in y:
    count = sum([1.0 for j in y if j > i])
    x.append(round(count / len(y) * 100, 1))
print(tuple(x))

答案 4 :(得分:-1)

我将使用以10为底的对数创建扩展属性。

如果您希望-也计为负数,则为:

import kotlin.math.log10

val Int.length get() = when {
    this == 0 -> 1
    this < 0 -> log10(-toFloat()).toInt() + 2
    else -> log10(toFloat()).toInt() + 1
}

如果您只想计算计数的数字,而忽略负数的-则为:

import kotlin.math.absoluteValue
import kotlin.math.log10

val Int.length get() = when(this) {
    0 -> 1
    else -> log10(toFloat().absoluteValue).toInt() + 1
}

然后您可以做

println(1234.length)
println((-1234).length)