Имеется натуральное число n. Как получить число цифр в этом числе?
int n = 33;
int numberDigits = ???
Ответ
Не надо никаких циклов, можно использовать логарифм
Math.ceil(Math.log10(x))
Для страховки можно использовать Math.ceil(Math.log10(x + 0.5))
Собственно, проверил и получил такие вот результаты (3 варианта вычисления: логарифм, деление, сдвиг):
Логарифм работает за константное время и, согласен, не так уж быстро, как хотелось бы
Сдвиг и деление работают линейно от длины числа, причем сдвиг примерно в пять раз быстрее деления.
На десятизначных числах на long(это как раз порядка Integer.MAX_VALUE) логарифм так же быстр, как и сдвиг.
Вот, теперь можно почти точно сказать, что логарифм следует использовать только для long, и то, лишь с уверенностью, что будут меряться действительно длинные числа, больше десяти знаков.
Вот тестилка, можно и самим проверить, кто желает. На вход подается количество итераций.
import sun.misc.Perf;
public class IntegerMeter{
static Perf perf = Perf.getPerf();
static long frequency = perf.highResFrequency();
static int countDigits_A(long number){
int result = 0;
for(long match = 0L; number > match; ++result)
match = (match << 3) + (match << 1) + 9L;
return result;
}
static int countDigits_B(long number){
return (int) Math.ceil(Math.log10(number + 0.5));
}
static int countDigits_C(long number){
int result = 0;
while(number != 0L){
++result;
number /= 10;
}
return result;
}
static int countDigits_A(int number){
int result = 0;
for(int match = 0; number > match; ++result)
match = (match << 3) + (match << 1) + 9;
return result;
}
static int countDigits_B(int number){
return (int) Math.ceil(Math.log10(number + 0.5));
}
static int countDigits_C(int number){
int result = 0;
while(number != 0){
++result;
number /= 10;
}
return result;
}
private static double test(Runnable runnable, int count){
long begin = perf.highResCounter();
while(count-- > 0) runnable.run();
long end = perf.highResCounter();
return (double)(end - begin) / frequency;
}
public static void main(String[] args){
final long candidateLong = 5464456734L;
final int candidateInt = (int) candidateLong;
int count = Integer.parseInt(args[0]);
double testLong_A = test(new Runnable(){
public void run(){ countDigits_A(candidateLong); }
}, count);
double testLong_B = test(new Runnable(){
public void run(){ countDigits_B(candidateLong); }
}, count);
double testLong_C = test(new Runnable(){
public void run(){ countDigits_C(candidateLong); }
}, count);
double testInt_A = test(new Runnable(){
public void run(){ countDigits_A(candidateInt); }
}, count);
double testInt_B = test(new Runnable(){
public void run(){ countDigits_B(candidateInt); }
}, count);
double testInt_C = test(new Runnable(){
public void run(){ countDigits_C(candidateInt); }
}, count);
System.out.printf("%.5f\t%.5f\t%.5f
%.5f\t%.5f\t%.5f
",
testLong_A, testLong_B, testLong_C, testInt_A, testInt_B, testInt_C);
}
}
Комментариев нет:
Отправить комментарий