计算Kotlin中的位数

计算Kotlin中的位数,kotlin,Kotlin,我目前正在使用简单的string.length方法计算位数: val number = 829 val length = number.toString().length 我想知道这是一种好方法还是有一种更合适的方法在Kotlin中实现这一点。您可以在Java.lang.math中使用标准Java数学库(编辑:由于Kotlin 1.2,请使用Kotlin.math)。log10函数将给出数字的长度减去1(有些例外)。不过,此函数与double一起工作,因此必须来回转换 Kotlin中的leng

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

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

我想知道这是一种好方法还是有一种更合适的方法在Kotlin中实现这一点。

您可以在
Java.lang.math
中使用标准Java数学库(编辑:由于Kotlin 1.2,请使用
Kotlin.math
)。
log10
函数将给出数字的长度减去1(有些例外)。不过,此函数与double一起工作,因此必须来回转换

Kotlin中的
length
函数可以这样编写:

fun Int.length() = when(this) {
    0 -> 1
    else -> log10(abs(toDouble())).toInt() + 1
}
然后你可以这样称呼它:

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

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

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

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

我将使用以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)

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

  • 检查该数字是否符合范围
    -9..9
    。如果这是真的,结果是1
  • 否则,将数字除以10,对结果中的数字进行计数,然后将该计数加1

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


是的,除了负数,它们的长度中会有负号。一些使用“log”的解决方案也会起作用。由于Kotlin 1.2,您可以使用
absoluteValue
。这包括负数
number.absoluteValue.toString().length
唯一错误的情况是
number
Int.MIN\u值
,而下面答案中的数字解对性能更好,问题中的原始代码可以简化为
“$number.length
,在我看来,这看起来更简洁。不过,我不建议在真正的代码中使用它。我想知道为什么标准库中没有包含它。顺便问一下,检查'Int.MIN\u VALUE->10'的条件是什么?因为
Math.abs(Int.MIN\u VALUE)
溢出,我只是硬编码了它
Int.MIN_值
等于
-2147483648
,长度为10位。如果先转换为double,然后计算绝对值,则可以去掉
Int.MIN_值
特例:
else->Math.log10(Math.abs(toDouble()).toInt()+1
,很好。已编辑。关于此解决方案的一些注释在我的回答中有不同的做法:1。我不会使用
java.lang.Math
方法,而是使用
kotlin.Math
函数,这样它就独立于底层运行时。2.我将使用扩展属性,而不是扩展函数。3.第二个示例是错误的,它将在计算
1234.length()
时打印
-4
,然后对结果求反,您需要将
-1234
放在括号中,如
println((-1234.length())
。我相信其他人可能会发现它很有用,但就我而言,这有点过头了。我只是在找一句俏皮话。不过,谢谢你的反馈。对于负数的位数,你不需要取绝对值吗?似乎是一件小事。。。还是我遗漏了什么?@thecoshman
Math.abs(Int.MIN\u VALUE)
仍然是负数。。。一个经典:)@fredsoverflow,这实际上是非常有意义的。想想4位2的恭维数字。最小的数字是-8,而最大的数字是7(当然是1000和0111)。-8的绝对值为8;它的二进制值应该是
1000
,但是我们有两个补充,所以它被解释为它自己。耶,电脑!
println(1234.length)
println((-1234).length)
fun numberOfDigits(n: Int): Int = 
    when (n) {
        in -9..9 -> 1
        else -> 1 + numberOfDigits(n / 10)
    } 
fun countDigits(str: String): Int = str.filter{ Character.isDigit(it) }.count()

// countDigits("-11.345F") == 5