我想知道,是否有 Scala 内置方法来获取整数的十进制表示的长度?
示例:45
有长度2
;10321
有长度5
。
可以使用 来获取长度10321.toString.length
,但是由于创建 String 对象时的开销,这有点难闻。有没有更好的方法或内置方法?
更新:
- “更好”是指更快的解决方案
- 我只对正整数感兴趣
这绝对是个人喜好,但我认为对数方法没有分支看起来更好。仅对于正值,当abs
然可以省略。
def digits(x: Int) = {
import math._
ceil(log(abs(x)+1)/log(10)).toInt
}
如果您想要速度,那么假设随机分布,以下内容非常好:
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
如果你想要的只是地板,那么计算双精度的对数是没有效率的。
传统的递归方式是:
def len(x: Int, i: Int = 1): Int =
if (x < 10) i
else len(x / 10, i + 1)
这比获取 0 到 10e8 范围内的整数的日志要快。
lengthBase10
上面的速度比其他任何东西快大约 4 倍。
toString
那么 get length
of int 将不适用于负整数。此代码不仅适用于正数,也适用于负数。
def digits(n:Int) = if (n==0) 1 else math.log10(math.abs(n)).toInt + 1;
像这样的东西应该可以完成这项工作:
def numericLength(n: Int): Int = BigDecimal(n).precision
将日志以 10 为底,在地板上加 1。
最简单的方法是:
def numberLength(i : Int): Int = i.toString.length
您可以添加一个保护条件,因为负数Int
的长度为 abs + 1。
大多数人给出了 (int) log(number)+1 的最有效答案,但我想更深入地了解为什么会这样。
设 N 为 3 位数字。这意味着 N 可以是 100 到 1000 之间的任何数字,或者:
100 < N < 1000 => 10^2 < N < 10^3
对数函数是连续的,因此:
日志(10^2) < 日志(N) < 日志(10^3) => 2 < 日志(N) < 3
我们可以得出结论,N 的对数是 2 到 3 之间的数字,或者换句话说,任何 3 位数字的对数都在 2 到 3 之间。
因此,如果我们只取数字对数的整数部分(例如,2.567 的整数部分是 2)并加上 1,我们就得到了数字的数字长度。
另一种可能是:
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)
这是解决方案:
number.toString.toCharArray.size
输入输出
45 - 2
100 - 3