有没有比这个方法更简洁的方法来获取整数的位数?
int numDigits = String.valueOf(1000).length();
有没有比这个方法更简洁的方法来获取整数的位数?
int numDigits = String.valueOf(1000).length();
当前回答
你的基于字符串的解决方案是完全OK的,没有什么“不整洁”的。你必须意识到,在数学上,数字没有长度,也没有数字。长度和数字都是数字在特定基底(即字符串)中的物理表示形式的属性。
基于对数的解决方案在内部完成(部分)与基于字符串的解决方案相同的工作,并且可能(微不足道地)更快,因为它只生成长度而忽略数字。但实际上我并不认为它的意图更明确——这是最重要的因素。
其他回答
出于好奇,我试着对其进行基准测试……
import org.junit.Test;
import static org.junit.Assert.*;
public class TestStack1306727 {
@Test
public void bench(){
int number=1000;
int a= String.valueOf(number).length();
int b= 1 + (int)Math.floor(Math.log10(number));
assertEquals(a,b);
int i=0;
int s=0;
long startTime = System.currentTimeMillis();
for(i=0, s=0; i< 100000000; i++){
a= String.valueOf(number).length();
s+=a;
}
long stopTime = System.currentTimeMillis();
long runTime = stopTime - startTime;
System.out.println("Run time 1: " + runTime);
System.out.println("s: "+s);
startTime = System.currentTimeMillis();
for(i=0,s=0; i< 100000000; i++){
b= number==0?1:(1 + (int)Math.floor(Math.log10(Math.abs(number))));
s+=b;
}
stopTime = System.currentTimeMillis();
runTime = stopTime - startTime;
System.out.println("Run time 2: " + runTime);
System.out.println("s: "+s);
assertEquals(a,b);
}
}
结果如下:
Run time 1: 6765 s: 400000000 Run time 2: 6000 s: 400000000
现在我想知道我的基准测试是否真的意味着什么,但我确实在基准测试本身的多次运行中得到了一致的结果(一毫秒内的变化)……:)看起来这是无用的尝试和优化…
编辑:根据ptomli的注释,我在上面的代码中用' I '替换'number',并在5次运行的bench中得到以下结果:
Run time 1: 11500 s: 788888890 Run time 2: 8547 s: 788888890 Run time 1: 11485 s: 788888890 Run time 2: 8547 s: 788888890 Run time 1: 11469 s: 788888890 Run time 2: 8547 s: 788888890 Run time 1: 11500 s: 788888890 Run time 2: 8547 s: 788888890 Run time 1: 11484 s: 788888890 Run time 2: 8547 s: 788888890
Two comments on your benchmark: Java is a complex environment, what with just-in-time compiling and garbage collection and so forth, so to get a fair comparison, whenever I run a benchmark, I always: (a) enclose the two tests in a loop that runs them in sequence 5 or 10 times. Quite often the runtime on the second pass through the loop is quite different from the first. And (b) After each "approach", I do a System.gc() to try to trigger a garbage collection. Otherwise, the first approach might generate a bunch of objects, but not quite enough to force a garbage collection, then the second approach creates a few objects, the heap is exhausted, and garbage collection runs. Then the second approach is "charged" for picking up the garbage left by the first approach. Very unfair!
也就是说,上述两种方法在本例中都没有产生显著差异。
不管有没有这些修改,我得到的结果和你完全不同。当我运行这个时,是的,toString方法给出的运行时间为6400到6600 millis,而log方法给出的运行时间为20,000到20,400 millis。对数方法对我来说不是稍微快一点,而是慢了3倍。
请注意,这两种方法涉及非常不同的代价,所以这并不完全令人震惊:toString方法将创建许多必须清理的临时对象,而log方法需要更密集的计算。因此,可能区别在于,在内存较少的机器上,toString需要更多的垃圾收集回合,而在处理器较慢的机器上,额外的log计算将更加痛苦。
我还尝试了第三种方法。我写了这个小函数:
static int numlength(int n)
{
if (n == 0) return 1;
int l;
n=Math.abs(n);
for (l=0;n>0;++l)
n/=10;
return l;
}
在我的机器上,它运行在1600到1900毫厘之间——不到toString方法的1/3,log方法的1/10。
如果您的数字范围很广,您可以通过开始除以1000或1,000,000来进一步加快速度,以减少循环的次数。我还没玩过。
没有字符串API,没有utils,没有类型转换,只是纯java迭代->
public static int getNumberOfDigits(int input) {
int numOfDigits = 1;
int base = 1;
while (input >= base * 10) {
base = base * 10;
numOfDigits++;
}
return numOfDigits;
}
如果你愿意,你可以追求更大的价值。
你的基于字符串的解决方案是完全OK的,没有什么“不整洁”的。你必须意识到,在数学上,数字没有长度,也没有数字。长度和数字都是数字在特定基底(即字符串)中的物理表示形式的属性。
基于对数的解决方案在内部完成(部分)与基于字符串的解决方案相同的工作,并且可能(微不足道地)更快,因为它只生成长度而忽略数字。但实际上我并不认为它的意图更明确——这是最重要的因素。
这取决于你对“整洁”的定义。我认为下面的代码相当简洁,运行速度也很快。
它基于Marian的回答,扩展到所有long值,并使用?:运营商。
private static long[] DIGITS = { 1l,
10l,
100l,
1000l,
10000l,
100000l,
1000000l,
10000000l,
100000000l,
1000000000l,
10000000000l,
100000000000l,
1000000000000l,
10000000000000l,
100000000000000l,
1000000000000000l,
10000000000000000l,
100000000000000000l,
1000000000000000000l };
public static int numberOfDigits(final long n)
{
return n == Long.MIN_VALUE ? 19 : n < 0l ? numberOfDigits(-n) :
n < DIGITS[8] ? // 1-8
n < DIGITS[4] ? // 1-4
n < DIGITS[2] ? // 1-2
n < DIGITS[1] ? 1 : 2 : // 1-2
n < DIGITS[3] ? 3 : 4 : // 3-4
n < DIGITS[6] ? // 5-8
n < DIGITS[5] ? 5 : 6 : // 5-6
n < DIGITS[7] ? 7 : 8 : // 7-8
n < DIGITS[16] ? // 9-16
n < DIGITS[12] ? // 9-12
n < DIGITS[10] ? // 9-10
n < DIGITS[9] ? 9 : 10 : // 9-10
n < DIGITS[11] ? 11 : 12 : // 11-12
n < DIGITS[14] ? // 13-16
n < DIGITS[13] ? 13 : 14 : // 13-14
n < DIGITS[15] ? 15 : 16 : // 15-16
n < DIGITS[17] ? 17 : // 17-19
n < DIGITS[18] ? 18 :
19;
}